笔记——多重背包

来源:互联网 发布:java微信支付查询订单 编辑:程序博客网 时间:2024/05/21 22:31
/*
多重背包
与01背包类似,每个背包有个可选择次数
将c用2进制的思想分解
也就是把w[i],v[i],c[i]的物品分解为w[i]*2^x1,v[i]*2^x1;......w[i]*2^xn,v[i]*2^xn;2^x1+2^x2+......+2^xn=c[i]
x1为0
转换为2进制来做
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int w[105];
int v[105];
int dp[105][105];
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    int num=1;
    for(int i=1;i<=n;i++){
        int wi,vi,ci;
        scanf("%d %d %d",&wi,&vi,&ci);
        int k=1;
        w[num]=wi;
        v[num++]=vi;
        ci-=1;
        while(ci){
            if(ci&1){
                w[num]=k*wi;
                v[num++]=k*vi;
            }
            k=k<<1;
            ci=ci>>1;
        }
    }
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=num;i++){
        for(int j=m;j>=0;j--){
            if(j>=w[i]){
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
            }
            else{
                dp[i][j]=dp[i-1][j];
            }
        }
    }
    printf("%d\n",dp[num][m]);
    return 0;
}