[Usaco2008 Nov]Buying Hay 購買幹草
阿新 • • 發佈:2019-05-14
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 購買幹草