【HDU】2191 多重背包问题
原题目:悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
【算法】多重背包(有限背包) 动态规划
【题解】http://blog.csdn.net/acdreamers/article/details/8563283
优化:若物品数量(num[i])*物品重量(w[i])>背包容量(m),就相当于无限背包。
对于num[i],可以拆成若干个01背包来实现1...num[i]的全覆盖,二进制原理:
1...k中的数可以由1.2.4...2t.k-2t+1+1(2t+2 > k ≥ 2t+1)组成。
具体实现见代码。
还有一种优先队列优化的有限背包算法,不介绍。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1010; int num[maxn],f[maxn],w[maxn],v[maxn],m,n; void zeroone_pack(int W,int V) { for(int i=m;i>=W;i--)f[i]=max(f[i],f[i-W]+V); } void complete_pack(int W,int V) { for(int i=W;i<=m;i++)f[i]=max(f[i],f[i-W]+V); } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&m,&n); memset(f,0,sizeof(f)); for(int i=1;i<=n;i++) scanf("%d%d%d",&w[i],&v[i],&num[i]);//w[i]重量 value[i]价值 for(int i=1;i<=n;i++) if(num[i]*w[i]>m)complete_pack(w[i],v[i]); else { int k=1; while(k<num[i]) { zeroone_pack(w[i]*k,v[i]*k); num[i]-=k; k<<=1; } zeroone_pack(w[i]*num[i],v[i]*num[i]); } printf("%d\n",f[m]); } return 0; }