混合背包问题(动态规划)
作者:互联网
混合背包问题
有 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
解题思路:
按照输入物品可以使用的次数,分类处理,可划分为01背包和完全背包两类进行处理
1 #include <iostream> 2 #include <algorithm> 3 #include <vector> 4 5 using namespace std; 6 7 constexpr int N = 1010; 8 typedef struct { 9 int type; // 物品处理的类型:-1(01背包问题), 0(完全背包问题) 10 int volume; // 物品的体积 11 int weight; // 物品的价值 12 } goods; 13 14 int main() { 15 int n = 0; // 物品个数 16 int v = 0; // 背包容量 17 std::cin >> n >> v; // 输入物品数量和背包容量 18 vector<goods> goodsList; 19 for (int i = 0; i < n; i++) { 20 int volume = 0; // 物品的体积 21 int weight = 0; // 物品的价值 22 int s = 0; // 某件物品可以用几次 23 std::cin >> volume >> weight >> s; // 输入物品的体积、价值和可以用的次数 24 // 根据某件物品可以用的次数,将物品分类处理: 25 // s < 0时按照01背包处理, s == 0时按照完全背包处理, 其它情况就是多重背包需转换为01背包处理 26 if (s < 0) { 27 goodsList.push_back({-1, volume, weight}); 28 } else if (s == 0) { 29 goodsList.push_back({0, volume, weight}); 30 } else { 31 for (int k = 1; k <= s; k *= 2) { 32 s -= k; 33 goodsList.push_back({-1, k * volume, k * weight}); 34 } 35 if (s > 0) { 36 goodsList.push_back({-1, s * volume, s * weight}); 37 } 38 } 39 } 40 vector<int> dp(N , 0); 41 for (auto goods : goodsList) { 42 // 按照01背包问题处理 43 if (goods.type < 0) { 44 for (int j = v; j >= goods.volume; j--) { 45 dp[j] = max(dp[j], dp[j - goods.volume] + goods.weight); 46 } 47 } else { // 按照完全背包处理 48 for (int j = goods.volume; j <= v; j++) { 49 dp[j] = max(dp[j], dp[j - goods.volume] + goods.weight); 50 } 51 } 52 } 53 std::cout << dp[v] << endl; 54 return 0; 55 }
标签:背包,weight,int,混合,volume,goods,物品,动态 来源: https://www.cnblogs.com/MGFangel/p/16147297.html