1. 程式人生 > >[Usaco2008 Nov]Buying Hay 購買幹草

[Usaco2008 Nov]Buying Hay 購買幹草

esp 背包 計算 等於 char fine pla ++ iostream

題目描述

約翰的幹草庫存已經告罄,他打算為奶牛們采購H(1≤H≤50000)磅幹草,他知道N(1≤N≤100)個幹草公司,現在用1到N給它們編號。第i個公司賣的幹草包重量為Pi(1≤Pi≤5000)磅,需要的開銷為Ci(l≤Ci≤5000)美元.每個幹草公司的貨源都十分充足,可以賣出無限多的幹草包.幫助約翰找到最小的開銷來滿足需要,即采購到至少H磅幹草.

輸入格式

第1行輸入N和H,之後N行每行輸入一個Pi和Ci.

輸出格式

最小的開銷.


與普通的完全背包不同的是,這題裝的幹草可以超過所需的重量。這裏介紹兩種常見的做法。

1.把背包總體積往上擴一段,也就是把背包容量擴大。設此時的容量為m‘。然後做完全背包即可。最後枚舉m~m‘的每一位,取最小代價。由於題中的Pi≤5000,所以讓m‘等於m+5000即可。

2.刷表法。設當前已經買了j磅的幹草,已經買了i-1種幹草,每種幹草的重量為ci、價格為vi。那麽:

\[ dp[j+c[i]]=Min(dp[j+c[i]],dp[j]+v[i]) \]

如果j+c[i]>m,那麽直接計算到dp[m]的頭上即可。所以把算式微調一下,改為:

\[ dp[Min(j+c[i],m)]=Min(dp[Min(j+c[i]),m],dp[j]+v[i]) \]

第一種的時間復雜度為O(N(M+Max{ci}));第二種為O(NM)。實際上跑得差不多快。

第二種的代碼:

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 101
#define maxm 50001
using namespace std;
 
int dp[maxm],c[maxn],v[maxn];
int n,m;
 
inline int read(){
    register int x(0),f(1); register char c(getchar());
    while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
    while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
 
int main(){
    n=read(),m=read();
    for(register int i=1;i<=n;i++) c[i]=read(),v[i]=read();
 
    memset(dp,0x3f,sizeof dp);
    dp[0]=0;
    for(register int i=1;i<=n;i++){
        for(register int j=0;j<=m;j++){
            dp[min(j+c[i],m)]=min(dp[min(j+c[i],m)],dp[j]+v[i]);
        }
    }
    printf("%d\n",dp[m]);
    return 0;
}

[Usaco2008 Nov]Buying Hay 購買幹草