【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;
}
View Code

 

posted @ 2017-02-15 18:48  ONION_CYC  阅读(506)  评论(0编辑  收藏  举报