题目描述
有 N
种物品和一个容量是 V
的背包。
物品一共有三类:
第一类物品只能用1次(01背包);
第二类物品可以用无限次(完全背包);
第三类物品最多只能用 si
次(多重背包);
每种体积是 vi
,价值是 wi
。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
输入格式
第一行两个整数,N,V
,用空格隔开,分别表示物品种数和背包容积。
接下来有 N
行,每行三个整数 vi,wi,si
,用空格隔开,分别表示第 i
种物品的体积、价值和数量。
si=−1
表示第 i
种物品只能用1次;
si=0
表示第 i
种物品可以用无限次;
si>0
表示第 i
种物品可以使用 si
次
样例
输入样例`
4 5
1 2 -1
2 4 1
3 4 0
4 5 2
输出样例
8
思路
统一转化为多重背包求解
C++ 代码
#import<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define pb push_back
#define sz(v) ((int)(v.size()))
#define fi first
#define se second
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef vector<int> vt;
const int N=2e5+10;
const int mod=1000000007;
int a[N],b[N];
int f[6050],v[5050],w[5050],s[5050];
signed main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n,m,k;
cin>>n>>m;
rep(i,1,n){
int x,y,g;
cin>>x>>y>>g;
v[i]=x;
w[i]=y;
if(g==-1)s[i]=1;//一次性物品的数量设为1
else if(g==0)s[i]=m/v[i];//无限多物品的数量设为当前背包容量所能装下该物品的最大数量
else s[i]=g;
}
//多重背包2dp
rep(i,1,n){
for(int k=1;s[i]>0;k<<=1){
int x=min(k,s[i]);
per(j,m,v[i]*x){
f[j]=max(f[j],f[j-x*v[i]]+x*w[i]);
}
s[i]-=x;
}
}
cout<<f[m];
return 0;
}