hdu 2191多重背包_二进制优化

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2191

题目很容易理解。

关于背包问题可以看dd enginer的《背包九讲》,链接:https://github.com/tianyicui/pack

这篇博客则用图片把背包问题讲的非常明了,同时讲了二进制优化多重背包问题,链接:http://blog.csdn.net/lyhvoyage/article/details/8545852

以下为没有经过二进制优化的代码:

#include <iostream>
using namespace std;
 
int nCases;
int nValue, nKind;
int value[105], weight[105], bag[105];
int nMultiplePack[105];
 
int main()
{
    //freopen("input.txt", "r", stdin);
    scanf("%d", &nCases);
    while(nCases--)
    {
        memset(nMultiplePack, 0, sizeof(nMultiplePack));
        scanf("%d %d", &nValue, &nKind);
        for(int i=0; i<nKind; ++i)
            scanf("%d %d %d", &value[i], &weight[i], &bag[i]);
        for(int i=0; i<nKind; ++i)
            for(int j=0; j<bag[i]; ++j)
                for(int k=nValue; k>=value[i]; --k)
                    if(nMultiplePack[k] < nMultiplePack[k-value[i]]+weight[i])
                        nMultiplePack[k] = nMultiplePack[k-value[i]] + weight[i];
        printf("%d\n", nMultiplePack[nValue]);
 
    }
    return 0;
}

以下为经过二进制优化的版本:

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    int nCase,Limit,nKind,i,j,v[111],w[111],c[111],dp[111];
    //v[]存价值,w[]存尺寸,c[]存件数
    //在本题中,价值是米的重量,尺寸是米的价格
    int count,Value[1111],size[1111];
    //count存储分解完后的物品总数
    //Value存储分解完后每件物品的价值
    //size存储分解完后每件物品的尺寸
    cin>>nCase;
    while(nCase--)
    {
        count=0;
        cin>>Limit>>nKind;
        for(i=0; i<nKind; i++)
        {
            cin>>w[i]>>v[i]>>c[i];
            //对该种类的c[i]件物品进行二进制分解
            for(j=1; j<=c[i]; j<<=1)
            {
                //<<右移1位,相当于乘2
                Value[count]=j*v[i];
                size[count++]=j*w[i];
                c[i]-=j;
            }
            if(c[i]>0)
            {
                Value[count]=c[i]*v[i];
                size[count++]=c[i]*w[i];
            }
        }
        //经过上面对每一种物品的分解,
        //现在Value[]存的就是分解后的物品价值
        //size[]存的就是分解后的物品尺寸
        //count就相当于原来的n
        //下面就直接用01背包算法来解
        memset(dp,0,sizeof(dp));
        for(i=0; i<count; i++)
            for(j=Limit; j>=size[i]; j--)
                if(dp[j]<dp[j-size[i]]+Value[i])
                    dp[j]=dp[j-size[i]]+Value[i];

        cout<<dp[Limit]<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值