八叶一刀·无仞剑

万物流转,无中生有,有归于无

导航

POJ1276

Posted on 2013-04-27 00:36  闪之剑圣  阅读(254)  评论(0编辑  收藏  举报

      这道题运用了多重背包的思想,所以这里重点讲一下多重背包的做法:

      0-1背包只要认真看过《算法竞赛入门经典》的应该已经掌握了。其实首先,我们可以将多重背包问题,转化为0-1背包问题,只要将数量为v的每一种物品“展开”看做v个价值相同的物品,然后用0-1背包的方法去求即可。但是这样肯定会TLE的。运用状态压缩的思想,将每一个容量为v,价值为p的物品转化为几个“权值”为1,2,2^2,……,2^(k-1),v-2^k+1的物品,将p与各项权值相乘得到其容量,将我们用此方法对每一个i得到的这些容量都存入一个数组中。该数组就可以作为一组新的物品,其价值和体积相等。

     然后我们用一维数组的0-1背包来做就行了。具体可以再参考《背包问题九讲》。

    

#include <stdio.h>
#include<stdlib.h>
int cash,n,d[11],c[11];
int max(int a,int b)
{
    if(a>b)
    return a;
    else
    return b;
}
int main()
{
    int i,j,k;
    while(scanf("%d%d",&cash,&n)!=EOF)
    {
        k=0;
        int v[100],dp[100005]={0};
        for(i=1;i<=n;i++)
        {
        scanf("%d%d",&c[i],&d[i]);
        j=1;
        int num=c[i];
        while(num>j)
        {
            num-=j;
            v[k++]=d[i]*j;
            j*=2;
        }
        if(num)
            v[k++]=num*d[i];
        }
        for(i=0;i<k;i++)
        for(j=cash;j>=0;j--)
        if(j-v[i]>=0)
        {
            dp[j]=max(dp[j-v[i]]+v[i],dp[j]);
        }
        printf("%d\n",dp[cash]);
    }
    return 0;
}