多重背包的两种解决方法(poj1276)

多重背包是指装入背包的若干见物品种,可以拿的数量有上限。


第一种就是二进制优化,转换成01背包,例如一件物品可以拿26件,每一件的权值是w,26可以写成(1+2+4+8)+11,所以就把这种物品分解成权重为w,2w,4w,8w,11w的五种物品,这五种物品组合,一定能组成小于等于26的任意一个数,这样就把有26件的一种物品换成了五种各有一件的物品,用01背包就能解决了。

poj1276的代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define mem(a) memset(a,0,sizeof(a))

using  namespace std;

int dp[100002];
int w[200];
int main()
{
    int ans_v;
    while(scanf("%d",&ans_v)!=EOF)
    {
        int t=0;
        int n;
        scanf("%d",&n);
        int i;
        for(i=0;i=w[i];--j)
            {
                dp[j]=max(dp[j],dp[j-w[i]]+w[i]);
            }
        }
        printf("%d\n",dp[ans_v]);

    }
}

而另一种方法是维护一个数组num,num[i][j]表示在往背包里试着装第i件物品时,背包容量使用了j时装了多少件i物品。cost[i]为物品i的体积,num[i][j]=num[j-cost[i]]+1;可以看到num[i][j]和num[t|t!=i][j|j=1,2,....v]没有任何关系,所以可以省掉第一维,对于每一种物品,清空num,只计算num[j]就行了。

同样是poj1276的代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define mem(a) memset(a,0,sizeof(a))

using  namespace std;

int wi[20];
int mi[20];
int dp[100050];
int num[100050];

int main()
{
    int ans_v;
    while(scanf("%d",&ans_v)!=EOF)
    {
        int n;
        mem(dp);
        mem(num);
        scanf("%d",&n);
        int i;
        for(i=0;idp[j]&&num[j-wi[i]]


你可能感兴趣的:(poj训练计划,背包)