0%

混合背包

有 N 种物品和一个容量是 V 的背包。
物品一共有三类:

  1. 第一类物品只能用1次(s<0时)(01背包);
  2. 第二类物品可以用无限次(s=0时)(完全背包);
  3. 第三类物品最多只能用 $s_i$ 次(s>0时)(多重背包);
    每种体积是 $v_i$,价值是 $w_i$。
  • 求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
    输出最大价值。 思路:

    按类别处理就行,要注意的就是将多重背包转化为二进制优化的01背包就行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N=1010;
int f[N];
int n,m;
struct Goods{
int type,v,w;
};
vector<Goods>goods;
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
int v,w,s;
cin>>v>>w>>s;
if(s>0){
for(int k=1;k<=s;k*=2){
goods.push_back({-1,k*v,k*w});
s-=k;
}
if(s>0)goods.push_back({-1,s*v,s*w});
}
else goods.push_back({s,v,w});
}
for(auto g:goods){
if(!g.type){
for(int j=g.v;j<=m;j++)f[j] = max(f[j],f[j-g.v]+g.w);
}else {
for(int j=m;j>=g.v;j--)f[j] = max(f[j],f[j-g.v]+g.w);
}
}
cout<<f[m]<<endl;
return 0;
}