多重背包问题详解(C++实现)
多重背包问题是背包问题的一种变体,允许每种物品有多个单位可以选择,但每种物品都有一个数量上限,即最多只能选取该物品的指定数量。
也就是说,多重背包和 0-1 背包、完全背包的区别是:
以下是多重背包问题的示例程序代码:
二进制优化的实现代码如下:
也就是说,多重背包和 0-1 背包、完全背包的区别是:
- 0-1 背包问题:每种物品只有一件;
- 完全背包问题:每种物品可以选取无限件;
- 多重背包问题:每种物品可以选取有限件。
以下是多重背包问题的示例程序代码:
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; // 定义常量 N,表示数组的最大长度 int a[N], b[N], t = 0, n, m, dp[N], v, w, s; // 定义变量 a、b、t、n、m、dp、v、w、s int main() { cin >> n >> m; // 输入物品数量和背包容量 while (n--) { // 遍历每件物品 cin >> v >> w >> s; // 输入物品的价值、重量和数量 while (s--) { // 将多重背包拆成 0-1 背包 a[++t] = v; // 记录物品的价值 b[t] = w; // 记录物品的重量 } } for (int i = 1; i <= t; i++) // 遍历所有物品 for (int j = m; j >= a[i]; j--) // 从背包容量到物品重量逆序遍历 dp[j] = max(dp[j - a[i]] + b[i], dp[j]); // 更新 dp 数组,套用 0-1 背包问题的动态规划转移方程 cout << dp[m] << endl; // 输出最大总价值 return 0; }运行结果为:
3 10
1 2 3
2 3 2
3 4 2
16
二进制优化的实现代码如下:
#include <bits/stdc++.h> using namespace std; const int N = 12010, M = 2010; // 定义常量 N 和 M,分别表示物品总数量和背包容量 int n, m; // 物品数量和背包容量 int v[N], w[N]; // 定义物品体积和价值 int f[M]; // 定义动态规划数组 int main() { cin >> n >> m; // 输入物品数量和背包容量 int cnt = 0; // 用于记录分组数量 for (int i = 1; i <= n; i++) { int a, b, s; cin >> a >> b >> s; // 输入物品的体积、价值和数量上限 int k = 1; // 初始化二进制拆分因子 while (k <= s) { cnt++; // 增加组别计数 v[cnt] = a * k; // 计算组别总体积 w[cnt] = b * k; // 计算组别总价值 s -= k; // 剩余物品数量减少 k *= 2; // 二进制拆分因子翻倍 } // 处理剩余物品 if (s > 0) { cnt++; v[cnt] = a * s; w[cnt] = b * s; } } n = cnt; // 更新总组数为分组后的组别数量 // 转换为 0-1 背包问题 for (int i = 1; i <= n; i++) for (int j = m; j >= v[i]; j--) f[j] = max(f[j], f[j - v[i]] + w[i]); // 更新动态规划数组 cout << f[m] << endl; // 输出最大总价值 return 0; }运行结果为:
3 10
1 2 3
2 3 2
3 4 2
16