睡前小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~

 

posted @ 2015-12-06 01:38  Helica  阅读(178)  评论(0编辑  收藏  举报