dp汇总 多重背包问题

多重背包

整体思路:转为01背包

使用二进制优化,将每一类物品都打包,最后选择一包包的要不要选

N开多大? 

nlogs(其中n是类别数,s是每个类的数量)

为什么是logs? 最差情况是logs

为什么,思考一下:2^0+2^1+2^2+2^3=2^4-1  也就是对于s=16个物品,logs=4

2^0+2^1+2^2+2^3=15  这里是四包  最后剩出来的1个分成一包,(1<16)

代码:

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 12000,M = 2010;
int w[N],v[N];//打包后的每一包的价值和体积
int dp[M];
int n,m;
int main()
{
    cin>>n>>m;
    int k=1; //打成了几包
    for(int i=1;i<=n;i++)
    {
        int value,volum,s;
        cin>>volum>>value>>s;
        int a=1;
        while(a<=s)
        {
            s-=a;
            w[k]=a*value;
            v[k]=a*volum;
            a*=2;
            k++;
        }
        if(s)
        {
            w[k]=s*value;
            v[k]=s*volum;
            k++;
        }
    }
    k--;
    for(int i=1;i<=k;i++)
        for(int j=m;j>=v[i];j--)
        {
            dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
        }
    cout<<dp[m];
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值