睡前小dp-poj1276-多重背包+二进制优化
http://poj.org/problem?id=1276
简单的多重背包,不过需要优化一下才能过。网上还有暴力的做法。
二进制优化在背包九讲里讲的比较清楚。对于多重背包的每一件物品,使用二进制的形式表示。
比如5件A价值物品,可以表示成1件1*A价值物品+1件2*A价值物品+1件2*A价值物品。
这三种物品就能表示选取原5种A物品所有的情况。从m变成了logm。
最后利用01背包来解决。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int cash,N; int v[2000],n[2000],dp[110000],t[30000]; int main() { while(~scanf("%d%d",&cash,&N)) { int cnt = 0; for(int i=1;i<=N;i++) { scanf("%d%d",&n[i],&v[i]); if(n[i] == 0||v[i] == 0) continue; int k = 1; while(n[i]-k>0) { t[cnt++] = k*v[i]; n[i]-=k; k<<=1; } if(n[i]) t[cnt++] = v[i]*n[i]; } memset(dp,0,sizeof dp); for(int i=0;i<cnt;i++) { for(int j=cash;j>=t[i];j--) { dp[j] = max(dp[j],dp[j-t[i]]+t[i]); } } printf("%d\n",dp[cash]); } }
//听队友说睡前适合做dp~