您的位置:首页 > 其它

【HDU】2191 多重背包问题

2017-02-15 18:48 204 查看

原题目:悼念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;
}
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: