混合背包

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000+10;
int n,k,w[maxn],v[maxn],dp[10*maxn]={0},nw[10*maxn],nv[10*maxn],cnt=0,c[maxn];
//计算出完全背包最多多少个,就变成了多重背包,01页看成多重,直接用二进制变成01,然后dp
//也可以完全背包不转化,用标记来和01区分,然后dp时根据不同的类型进行不同的for循环,可以滚动数组,这样快因为完全背包优化过了
//也可以直接对所有的分类,根据0 1 2,进行选择然后for循环,有完全背包的优化,快
int main() {
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>w[i]>>v[i]>>c[i];
        if(c[i]==-1) c[i]=1;
        if(c[i]==0) c[i]=k/w[i];//最多1000次
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=c[i];j<<=1){
            c[i]-=j;
            nv[++cnt]=v[i]*j;
            nw[cnt]=w[i]*j;
        }
        if(c[i]>0){
            nv[++cnt]=v[i]*c[i];
            nw[cnt]=w[i]*c[i];
        }
    }
    for(int i=1;i<=cnt;i++){
        for(int j=k;j>=nw[i];j--){
                dp[j]=max(dp[j],dp[j-nw[i]]+nv[i]);
        }
    }
    cout<<dp[k]<<endl;
    return 0;
}

 

posted @ 2020-06-06 20:58  西伯利亚挖土豆  阅读(110)  评论(0编辑  收藏  举报