acwing 7 混合背包

习题地址  https://www.acwing.com/problem/content/description/7/

 

题目描述
有 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 次;
输出格式
输出一个整数,表示最大价值。

数据范围
0<N,V≤1000
0<vi,wi≤1000
−1≤si≤1000

输入样例
4 5
1 2 -1
2 4 1
3 4 0
4 5 2
输出样例:
8

 

算法1
前三种背包处理的混合型号
01 背包则直接放入数据容器中
多重背包则化解成 01 背包 放入数据容器中(见多重背包II习题 进行二进制优化)
完全背包也直接放入数据容器中

此刻数据容器vector[HTML_REMOVED] things;中就只有01背包和完全背包 那么就进行遍历处理

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 
 6 using namespace std;
 7 
 8 const int N = 1010;
 9 
10 int n,m;
11 int f[N];
12 
13 struct Thing{
14     int kind;
15     int v,w;
16 };
17 vector<Thing> things;
18 
19 
20 int main()
21 {
22     cin >> n>>m;
23     for(int i = 0;i<n;i++)
24     {
25         int v,w,s;
26         cin >> v >> w>> s;
27         if(s < 0)
28         {
29             things.push_back({-1,v,w});
30         }else if(s == 0) things.push_back({0,v,w});
31         else{
32             for(int k = 1;k <= s; k*=2){
33                 s -=k;
34                 things.push_back({-1,v*k,w*k});
35             }
36             if(s > 0) things.push_back({-1,v*s,w*s});
37         }
38     }
39 
40     for(auto thing:things)
41     {
42         if(thing.kind < 0){
43             for(int j = m;j >= thing.v;j--) f[j] = max(f[j],f[j-thing.v]+thing.w);
44         }else{
45             for(int j = thing.v;j <= m;j++) f[j] = max(f[j],f[j-thing.v]+thing.w);
46         }
47     }
48 
49     cout << f[m] << endl;
50 
51     return 0;
52 }
53 
54 作者:defddr
55 链接:https://www.acwing.com/solution/acwing/content/2198/
56 来源:AcWing
57 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Code

 

posted on 2019-05-23 17:48  itdef  阅读(286)  评论(0编辑  收藏  举报

导航