Skip to content

P1776 宝物筛选

bit manipulation,dp, https://www.luogu.com.cn/problem/P1776

【姚博骞 物院】思路:多重背包可以把物品总数拆成若干二进制个数的和,这样加和可以模拟所有可能的选择个数。

cpp
//将每个物品数量拆成二进制个数的01背包
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int max(int a,int b){
    return (a>b)?a:b;
}
int min(int a,int b){
    return (a<b)?a:b;
}
int main(){
    int n,wmax;
    cin>>n>>wmax;//n还未输入时不能用n初始化数组
    vector<int> v(n);
    vector<int> w(n);
    vector<int> m(n);
    vector<int>dp(wmax+1,0);
    for(int i=0;i<n;i++){
        cin>>v[i]>>w[i]>>m[i];   
    }
    for(int i=0;i<n;i++)//考虑要不要选这个物品
    {
        int num=min(wmax/w[i],m[i]);
        for(int k=1;num>0;k<<=1){
            int cnt=min(k,num);
            int value=cnt*v[i];
            int weight=cnt*w[i];
            for(int j=wmax;j>=weight;j--){
                dp[j]=max(dp[j-weight]+value,dp[j]);
            }
            num-=cnt;
        }
    }
    cout<<dp[wmax];
}