多重背包问题详解(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
ICP备案:
公安联网备案: