news 2026/4/23 12:47:53

背包问题二进制优化:方法与使用要点

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
背包问题二进制优化:方法与使用要点

一、二进制优化的核心思想

1. 基本原理

把一个正整数s拆分成若干个2的幂次方(1, 2, 4, 8, ...)的和,再加上剩余的零头。

例如:s = 13

  • 拆分成:1 + 2 + 4 + 6

  • 这样就可以用4个组表示0-13的所有数字

2. 数学原理

任何一个正整数n都可以表示为:

n = a₀·2⁰ + a₁·2¹ + a₂·2² + ... + aₖ·2ᵏ + r

其中aᵢ是0或1,r是剩余部分(小于2ᵏ⁺¹)

二、二进制优化的方法

步骤1:物品拆分

对于每种物品(体积v,价值w,数量s):

vector<pair<int, int>> items; // 存储拆分后的物品(体积,价值) int k = 1; // 从1开始 ​ while (s > 0) { int amount = min(k, s); // 这一组的数量 items.push_back({v * amount, w * amount}); // 打包成一组 s -= amount; k *= 2; // 幂次增加 }

步骤2:转换为01背包

拆分后,对每组物品使用01背包算法:

for (auto &item : items) { int v_group = item.first; // 这一组的总体积 int w_group = item.second; // 这一组的总价值 for (int j = V; j >= v_group; j--) { dp[j] = max(dp[j], dp[j - v_group] + w_group); } }

三、使用要点

1.什么时候使用二进制优化?

  • 情况1:物品数量s很大(比如s ≥ 20)

  • 情况2:背包容量V较大(V ≥ 1000)

  • 情况3:物品种类n较多(n ≥ 50)

2.二进制优化的优点

原始方法二进制优化后
每个物品拆成s个每个物品拆成log₂(s)个
时间复杂度:O(n × s × V)时间复杂度:O(n × log(s) × V)
物品总数 = ∑s物品总数 = ∑log₂(s)

3.拆分的边界情况

// 正确写法 while (k <= s) { items.push_back({v * k, w * k}); s -= k; k *= 2; } if (s > 0) { items.push_back({v * s, w * s}); }

四、适用场景分析

场景1:多重背包问题

// 问题描述:n种物品,每种物品有体积v[i],价值w[i],数量s[i] // 背包容量V,求最大价值

必须用二进制优化的情况:

  • n = 100, s[i] = 1000, V = 1000

  • 计算量:100×1000×1000 = 1亿 → 100×10×1000 = 100万(优化100倍)

场景2:完全背包问题

// 完全背包:每种物品可以取无限次

不能用二进制优化,需要用完全背包的递推公式:

for (int j = v[i]; j <= V; j++) { dp[j] = max(dp[j], dp[j - v[i]] + w[i]); }

场景3:混合背包问题

// 有些物品只能取1次(01背包) // 有些物品可以取无限次(完全背包) // 有些物品可以取有限次(多重背包)

部分用二进制优化

if (s == -1) // 01背包 // 直接处理 else if (s == 0) // 完全背包 // 完全背包处理 else // 多重背包 // 二进制优化后处理

五、代码模板

#include <iostream> #include <vector> using namespace std; ​ int main() { int n, V; cin >> n >> V; vector<int> dp(V + 1, 0); vector<pair<int, int>> items; // 存放(体积, 价值) // 读取并拆分物品 for (int i = 0; i < n; i++) { int v, w, s; cin >> v >> w >> s; // 二进制拆分 int k = 1; while (k <= s) { items.push_back({v * k, w * k}); s -= k; k *= 2; } if (s > 0) { items.push_back({v * s, w * s}); } } // 01背包 for (auto &item : items) { for (int j = V; j >= item.first; j--) { dp[j] = max(dp[j], dp[j - item.first] + item.second); } } cout << dp[V] << endl; return 0; }

六、复杂度分析

优化前后对比

假设:n=100, 平均s=1000, V=1000

方法物品总数循环次数时间估算
朴素拆分100×1000=100,000100,000×1000=1亿约1秒
二进制优化100×10=1,0001,000×1000=100万约0.01秒

七、注意事项

1.不要过度拆分

如果s很小(比如s ≤ 10),直接朴素拆分即可,二进制优化反而增加复杂度。

2.注意数据范围

// 错误:可能会溢出 items.push_back({v * k, w * k}); // 正确:确保在int范围内 int group_v = v * k; int group_w = w * k; if (group_v > V) break; // 如果单组体积超过背包容量,可以跳过 items.push_back({group_v, group_w});

3.优化技巧

// 提前剪枝:如果物品总体积 > 背包容量,直接按完全背包处理 if (v * s >= V) { // 转换为完全背包 for (int j = v; j <= V; j++) { dp[j] = max(dp[j], dp[j - v] + w); } continue; }

八、总结口诀

物品数量多,拆分要巧妙, 二进制优化,效率提高高。 二幂来打包,零头单独搞, 转成01包,问题解决了。

记住:当s > 20时,考虑二进制优化;当s很小或V很小时,直接朴素拆分即可。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:33:19

Airtest遇到模拟器无法输入中文的情况该如何处理?

1. 前言 最近有收到粉丝的一些提问&#xff0c;使用Airtest的 text 接口&#xff0c;发现在部分模拟器上&#xff0c; text 无法输入中文&#xff0c;不知道该怎么处理。 今天我们就输入这个小问题&#xff0c;来详细聊一下。 2. Airtest的输入法简介 对于Android设备来说&…

作者头像 李华
网站建设 2026/4/14 8:38:29

Apollo存档管理器:PS4游戏进度的终极守护者

Apollo存档管理器&#xff1a;PS4游戏进度的终极守护者 【免费下载链接】apollo-ps4 Apollo Save Tool (PS4) 项目地址: https://gitcode.com/gh_mirrors/ap/apollo-ps4 掌握Apollo Save Tool&#xff0c;让你的每一份游戏记忆都得到完美保存。作为专业的PS4存档管理解决…

作者头像 李华
网站建设 2026/4/23 11:35:55

FanControl步进速率智能散热配置指南:实战静音调校技巧

在追求极致散热性能与静音体验的平衡中&#xff0c;FanControl的步进速率参数扮演着关键角色。通过精准的风扇响应优化和噪音控制技巧&#xff0c;本文将为你提供一套完整的智能散热配置方案。 【免费下载链接】FanControl.Releases This is the release repository for Fan Co…

作者头像 李华
网站建设 2026/4/21 17:34:59

2025工业电流测量三大趋势,AT4V H00如何适配场景升级?

2025年&#xff0c;全球精密电流传感器市场正迎来高速增长期&#xff0c;预计到2030年将实现年均15%以上的复合增长率&#xff0c;中国市场增速更是领跑全球。新能源发电、工业自动化、新能源汽车等领域的快速扩张&#xff0c;推动工业电流测量需求从“基础数据采集”向“高精度…

作者头像 李华
网站建设 2026/4/18 1:26:39

强力FreeMarker在线测试工具:即刻解决模板调试难题的终极方案

强力FreeMarker在线测试工具&#xff1a;即刻解决模板调试难题的终极方案 【免费下载链接】freemarker-online-tester Apache Freemarker Online Tester: 是一个用于在线测试 Apache Freemarker 模板的 Web 应用程序。它可以帮助开发者快速测试 Freemarker 模板的语法和功能。适…

作者头像 李华
网站建设 2026/4/22 3:48:45

【普中DSP28335开发攻略】-- 第 22 章 I2C-EEPROM 实验

(1)实验平台&#xff1a;普中DSP28335开发板 前面我们已经介绍了 F28335 的 SPI 接口&#xff0c; 在串行通信中&#xff0c; SCI、 SPI、 I2C等应用是非常广泛的&#xff0c; 对于 F28335 这类高级处理器&#xff0c; 片内自然会集成 I2C 总线接口&#xff0c; 但通常我们不使…

作者头像 李华