1. 问题定义
有一个容量为 的背包。 有 种物品,第 种物品的重量为 ,价值为 ,数量为 (每件物品最多可选 件)。 目标:选择物品装入背包,使得总重量不超过 ,且总价值最大。
2. 与 0-1 背包、完全背包的区别
0-1 背包:每种物品只有 1 件(选或不选)。 完全背包:每种物品无限件。 多重背包:每种物品有给定的有限件数 。
3. 基本思路
3.1 直接转化为 0-1 背包
3.2 二进制优化
3.3 单调队列优化
1. 二进制优化解法
思路
代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int multipleKnapsackBinary(int C, vector<int>& w, vector<int>& v, vector<int>& s) {
vector<int> new_w, new_v;
// 二进制拆分
for (int i = 0; i < w.size(); ++i) {
int cnt = s[i];
for (int k = 1; k <= cnt; k *= 2) {
new_w.push_back(k * w[i]);
new_v.push_back(k * v[i]);
cnt -= k;
}
if (cnt > 0) {
new_w.push_back(cnt * w[i]);
new_v.push_back(cnt * v[i]);
}
}
// 0-1 背包
vector<int> dp(C + 1, 0);
for (int i = 0; i < new_w.size(); ++i) {
for (int j = C; j >= new_w[i]; --j) {
dp[j] = max(dp[j], dp[j - new_w[i]] + new_v[i]);
}
}
return dp[C];
}
int main() {
int C = 10;
vector<int> w = {2, 3, 4};
vector<int> v = {3, 4, 5};
vector<int> s = {3, 2, 1}; // 物品数量
int result = multipleKnapsackBinary(C, w, v, s);
cout << "最大价值(二进制优化): " << result << endl; // 输出 13
return 0;
}
2. 单调队列优化解法
思路
代码
#include <iostream>
#include <vector>
#include <deque>
using namespace std;
int multipleKnapsackMonotonicQueue(int C, vector<int>& w, vector<int>& v, vector<int>& s) {
vector<int> dp(C + 1, 0);
for (int i = 0; i < w.size(); ++i) {
for (int r = 0; r < w[i]; ++r) {
deque<int> q;
for (int j = r; j <= C; j += w[i]) {
// 维护队列头部不超过物品数量限制
while (!q.empty() && q.front() < j - s[i] * w[i]) {
q.pop_front();
}
// 用偏移量计算当前候选值
while (!q.empty() && dp[q.back()] + (j - q.back()) / w[i] * v[i] <= dp[j]) {
q.pop_back();
}
q.push_back(j);
// 更新 dp[j]
if (!q.empty()) {
dp[j] = max(dp[j], dp[q.front()] + (j - q.front()) / w[i] * v[i]);
}
}
}
}
return dp[C];
}
int main() {
int C = 10;
vector<int> w = {2, 3, 4};
vector<int> v = {3, 4, 5};
vector<int> s = {3, 2, 1};
int result = multipleKnapsackMonotonicQueue(C, w, v, s);
cout << "最大价值(单调队列优化): " << result << endl; // 输出 13
return 0;
}
如何选择方法?
二进制优化:代码简单,适合大多数场景(如 LeetCode、ACM 竞赛)。 单调队列优化:效率更高,但实现复杂,适合对性能要求极高的场景(如 和 较大时)。
凌志编程机器人培训学校全体教师参加山东省青少年科···
由淄博市教体局,淄博市科协主办,凌志编程机器人培···
创客空间建设 能够给人们分享各种乐趣,通过电脑,···
在了解创客教育之前,我们首先了解下何为创客。创客···