混合背包

 Description

背包体积为C,给出N个物品,每个物品占用体积为Vi,价值为Wi,每个物品要么至多取1件,要么至多取Mi件(Mi > 1),要么数量无限,在所装物品总体积不超过C的前提下所装物品的价值的和的最大值是多少?

Input

多测试用例。

第一行两个数NCC ≤ 200000,N ≤ 200),下面N行每行三个数ViWiMi分别表示每个物品的体积、价值与数量,Mi=1表示至多取一件,Mi>1表示至多取Mi件,Mi=-1表示数量无限。

Output

输出一行结果:所装物品价值的最大值。

Sample Input

2 10
3 7 2
2 4 -1

Sample Output

22

#include <iostream>
#include <string.h>
#include <algorithm>
const int PMAX = 200002;//背包最大容量
int N,C;//N种物品和一个容量为C的背包
//物品最多有M件可用,重量是W,价值是V
int W[PMAX],V[PMAX],M[PMAX];
int dp[PMAX];//记录总价值
using namespace std;
int main()
{
    while(cin >> N >> C)
    {
        //N个物品,背包体积为C
        memset(dp,0,sizeof(dp));
        int sum,k=0;  //m=1表示至多取一件,m=-1表示可以数量无限
        for(int i=1;i<=N;i++){
           cin >> W[i] >> V[i] >> M[i];
           sum=1;
           //将多重背包转换为0-1背包
           if(M[i]>1){
                while(M[i]>sum){
                    k++;
                    W[N+k]=W[i]*sum;
                    V[N+k]=V[i]*sum;
                    M[N+k]=1;
                    M[i]-=sum;
                    sum*=2;
                }
                W[i]*=M[i];
                V[i]*=M[i];
                M[i]=1;
           }

        }
        for(int i=1;i<=N+k;i++){
            //0-1背包
            if(M[i]==1){
                for(int j=C;j>=W[i];j--)
                    dp[j]=max(dp[j],dp[j-W[i]]+V[i]);
            } //完全背包
            else{
                for(int j = W[i];j<=C;j++)
                    dp[j]=max(dp[j],dp[j-W[i]]+V[i]);
            }
        }
        cout<<dp[C]<<endl;
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/dichuan/p/8158139.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值