野牛程序员讲少儿编程之——多重背包【高级版】!(二进制优化)
作者:野牛程序员:2025-04-27 18:11:15算法阅读 2315
野牛程序员讲少儿编程之——多重背包【高级版】!(二进制优化)
? 野牛程序员讲少儿编程之——多重背包【高级版】!(二进制优化)
? 为什么要高级版?
在上一个普通版多重背包中,
每件物品拿多少次,是一个一个慢慢试的,
效率不太高,像在超市排长队结账一样慢。?
高级版用“二进制优化”技巧,直接加速!
像开了VIP快速通道,速度飞快!?️?
? 什么是二进制优化?
假设某个物品有 13件可以选。
如果一个一个拿,循环13次,累到吐。
二进制优化的思路是:
先拿1件(1个)
再拿2件(2个)
再拿4件(4个)
再拿6件(因为1+2+4=7,13-7=6,还剩6件可以直接拿)
这样最多循环 log₂(件数) 次!超级省时间!
? 高级版代码(附超详细注释)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
/**
* 多重背包高级版(使用二进制优化)
* @param W 背包总容量
* @param weights 每种宝贝的重量
* @param values 每种宝贝的价值
* @param counts 每种宝贝的数量限制
* @return 最大能获得的价值
*/
int multipleKnapsackBinary(int W, vector<int>& weights, vector<int>& values, vector<int>& counts) {
int n = weights.size();
vector<int> dp(W + 1, 0); // dp[w] 表示容量为 w 时的最大价值
for (int i = 0; i < n; i++) {
int weight = weights[i];
int value = values[i];
int count = counts[i];
int k = 1;
while (count > 0) {
int actual = min(k, count); // 本次真正取的数量
int new_weight = weight * actual;
int new_value = value * actual;
// 0-1背包方式,大到小更新
for (int w = W; w >= new_weight; w--) {
dp[w] = max(dp[w], dp[w - new_weight] + new_value);
}
count -= actual;
k *= 2; // 继续下一次,倍增
}
}
return dp[W];
}
int main() {
// 宝贝的重量(kg)
vector<int> weights = {1, 3, 4};
// 宝贝的价值(元)
vector<int> values = {150, 200, 300};
// 每种宝贝的最大数量
vector<int> counts = {5, 2, 1}; // 小熊饼干最多5包,游戏手柄2个,音响1个
// 背包总容量(kg)
int W = 10;
cout << "最多可以获得价值:" << multipleKnapsackBinary(W, weights, values, counts) << " 元" << endl;
return 0;
}? 核心思路解释
| 步骤 | 解释 |
|---|---|
| 1 | 每件物品的数量,拆成若干个2的幂次方的小物品 |
| 2 | 每个小物品就像独立的0-1背包物品 |
| 3 | 用0-1背包的更新方法,快速完成计算 |
| 4 | 保证不会超数量,又能大大减少循环次数 |
✨ 举个小例子
假设:
小熊饼干:5包可以拿
普通方式 → 试1包、2包、3包、4包、5包,慢死了!
高级方式:
第一次拿1包 (2⁰)
第二次拿2包(2¹)
第三次拿2包(剩余)
只需要3次!速度翻倍!
? 高级版 vs 普通版
| 项目 | 普通版 | 高级版(二进制优化) |
|---|---|---|
| 循环次数 | 按数量线性增长 | 按数量对数增长 |
| 执行速度 | 慢 | 快 |
| 编码难度 | 简单 | 稍难但酷炫 |
? 小总结
| 背包类型 | 特点 | 技巧 |
|---|---|---|
| 0-1背包 | 每个物品最多一次 | 经典动态规划 |
| 完全背包 | 每个物品无限次 | 小到大遍历 |
| 多重背包普通版 | 每个物品有限次 | 外层循环次数 |
| 多重背包高级版 | 每个物品有限次 | 二进制优化循环次数 |
? 小剧场
「小熊饼干最多5包,怎么办?」
——「二进制拆分!1包+2包+2包,搞定!不用每次慢慢加!」??
二进制优化,就是把拿物品这件事变成了玩魔法数字游戏,轻轻松松赢下背包王国的战斗!?
野牛程序员教少儿编程与信息学奥赛-微信|电话:15892516892

