【动态规划/背包问题】从「混合背包问题」看待三种传统背包问题

简介: 【动态规划/背包问题】从「混合背包问题」看待三种传统背包问题

网络异常,图片无法展示
|


回顾三种传统背包问题



前面我们已经学完了三种传统背包问题了。


这里再回顾一下三种传统背包:


  • 01 背包:强调每件物品**「只能选择一次」。对其进行「一维空间优化」并不能降低时间复杂度,进行「一维空间优化」时要求「容量维度“从大到小”进行遍历」**。
  • 完全背包:强调每件物品**「可以选择无限次」。对其进行「一维空间优化」具有数学意义,可以将时间复杂度从 降低到 ,进行「一维空间优化」时要求「容量维度“从小到大”进行遍历」**。
  • 多重背包:强调每件物品**「只能选择有限次」**。对其无论是进行「一维空间优化」还是「普通扁平化」都不能降低时间复杂度,要应用额外的优化手段:二进制优化单调队列优化


三种背包问题的**「难易程度」「递增」,但「重要程度」则是「递减」** 的。


虽然「多重背包」的 二进制优化单调队列优化 都比较 trick。


但其实「多重背包」并没有这么常见,以至于在 LeetCode 上我都没找到与「多重背包」相关的题目。


同时三种背包问题都有**「不超过」「恰好」**两种状态定义。


这两种状态定义只在「初始化」上有区别。


至于该如何初始化则要抓住 什么样的状态是合法的 :


  • 对于「不超过」的状态定义: 均为合法值 。
    代表不考虑任何物品,背包容量「不超过 」的所取得的最大价值为 。
  • 对于「恰好」的状态定义: 中只有 为合法值 ,其他值均为“无效值”。
    代表不考虑任何物品,只有背包容量「恰好为 」时所取得的最大价值为 ;其他容量「恰好为非 」是无法取得有效价值的(因为不考虑任何物品)。


总的来说,三种背包问题都很经典(本质上都是组合优化问题),以至于「背包问题」直接成为了一类的动态规划模型。


我的建议是三种背包都需要掌握。但如果实在要分侧重点的话,我更愿意你将大多数时间花在「01 背包」和「完全背包」上。


混合背包



给定物品数量 和背包容量 。第 件物品的体积是 ,价值是 ,可用数量为 :


  • 当 为 代表是该物品只能用一次
  • 当 为 代表该物品可以使用无限次
  • 当 为任意正整数则代表可用 次


求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。


基本分析



混合背包其实就是综合了「01 背包」、「完全背包」和「多重背包」三种传统背包问题。


我们知道在一维空间优化方式中「01 背包」将当前容量 按照“从大到小”进行遍历,而「完全背包」则是将当前容量 按照“从小到大”进行遍历。


同时「多重背包」可以通过「二进制优化」彻底转移成「01 背包」。


所以我们只需要根据第 个物品是「01 背包」物品还是「完全背包」物品,选择不同的遍历顺序即可。


代码:


class Solution {
    public int maxValue(int N, int C, int[] w, int[] v, int[] s) {
        // 构造出物品的「价值」和「体积」列表
        List<Integer> worth = new ArrayList<>();
        List<Integer> volume = new ArrayList<>();
        for (int i = 0; i < N; i++) {
            int type = s[i];
            // 多重背包:应用「二进制优化」转换为 0-1 背包问题
            if (type > 0) { 
                for (int k = 1; k <= type; k *= 2) {
                    type -= k;
                    worth.add(w[i] * k);
                    volume.add(v[i] * k);
                }
                if (type > 0) {
                    worth.add(w[i] * type);
                    volume.add(v[i] * type);
                }
            // 01 背包:直接添加
            } else if (type == -1) {
                worth.add(w[i]);
                volume.add(v[i]);
            // 完全背包:对 worth 做翻转进行标记
            } else {
                worth.add(-w[i]);
                volume.add(v[i]);
            }
        }
        // 使用「一维空间优化」方式求解三种背包问题
        int[] dp = new int[C + 1];
        for (int i = 0; i < worth.size(); i++) {
            int wor = worth.get(i);
            int vol = volume.get(i);
            // 完全背包:容量「从小到大」进行遍历
            if (wor < 0) { 
                for (int j = vol; j <= C; j++) {
                    // 同时记得将 worth 重新翻转为正整数
                    dp[j] = Math.max(dp[j], dp[j - vol] - wor); 
                }
            // 01 背包:包括「原本的 01 背包」和「经过二进制优化的完全背包」
            // 容量「从大到小」进行遍历
            } else { 
                for (int j = C; j >= vol; j--) {
                    dp[j] = Math.max(dp[j], dp[j - vol] + wor);
                }
            }
        }
        return dp[C];
    }
}
复制代码


就这样我们解决了这个混合背包问题。


先将一个「多重背包」问题通过「二进制优化」的思路,转化为「01 背包」问题。


然后根据物品是属于「01 背包」还是「完全背包」决定容量 是"从大到小"还是"从小到大"进行推算。


换句话说就是根据物品的类型不同,选择不同的转移方式。


总结



今天我们在学习「混合背包」之前先梳理了前面学的三种传统背包问题。


三种传统背包的主要区别在于「物品可被选择的次数」,其中「01 背包」的一维空间的优化方式是其余背包问题的基础。


对于「完全背包」和「多重背包」而言,一个可以选择「任意个数的物品」,另外一个则存在「选择物品的上界」。


这导致这两种背包问题在转移某个 时,其实本质是分别在求「整个前缀的最值」和「滑动窗口的最值」。


这就意味着「完全背包」可以直接通过一维空间优化降低时间复杂度;而「多重背包」则要通过「二进制优化」(减少总的物品数量)或者「单调队列优化」(实现直接求得滑动窗口最值)来降低时间复杂度。


背包问题(目录)



  1. 01背包 : 背包问题 第一讲
  1. 【学习&练习】01背包 : 背包问题 第三讲
  2. 完全背包 : 背包问题 第四讲
  1. 多重背包 : 背包问题 第八讲
  2. 多重背包(优化篇)
  1. 混合背包 : 背包问题 第十一讲
  2. 分组背包 : 背包问题 第十二讲
  1. 多维背包 : 背包问题 第十四讲
  • 【练习】多维背包
  1. 树形背包
  • 【练习篇】树形背包
  1. 背包求方案数
  • 【练习】背包求方案数
  1. 背包求具体方案
  • 【练习】背包求具体方案
  1. 泛化背包
  • 【练习】泛化背包


最后



到这一节结束,我们就已经完成「背包问题」的第一阶段的学习了 🎉 🎉


接下来的「背包问题」更多的偏向于「多维」、「分组」、「有依赖」、「求方案数/具体方案」此类问题。


这类问题往往才是真正用来考察「背包思维」的题目,第一阶段的学习更多的是模板题,打基础用的。


继续加油吧 ~

相关文章
|
4月前
|
人工智能 自然语言处理 Cloud Native
AI数据分析师:阿里云AI认证 vs CAIE AI认证 ,企业更认哪个?
在AI技术全面渗透企业运营、数据驱动决策成为核心竞争力的背景下,AI数据分析师作为衔接技术与业务的关键角色,其专业能力认证已成为企业筛选人才的重要标尺。CAIE(注册人工智能工程师)AI认证与阿里云AI认证是当前国内市场关注度较高的两类认证,但二者的定位、知识体系与适配场景存在显著差异,企业对其认可程度也因行业属性、业务需求不同而有所分化。本文将从认证核心价值、企业认可逻辑、适配场景三个维度,拆解两类认证的企业认可度差异,为AI数据分析师的职业发展与认证选择提供参考。
|
5月前
|
人工智能 异构计算
从帧到世界:面向世界模型的长视频生成
《从帧到世界》介绍面向世界模型的长视频生成新范式MMPL,由南京大学范琦团队提出。该方法通过“微观规划+宏观规划”双阶段策略,解决传统生成中的时域漂移与串行瓶颈,实现高物理合理性、强时空连贯的长视频生成,支持并行加速,为世界模型提供认知与预测世界的AI基础设施。
352 1
从帧到世界:面向世界模型的长视频生成
|
4月前
|
数据采集 存储 监控
数据资产是什么?企业该如何做好数据资产管理?
企业常陷数据内耗:报表打架、口径不一、决策靠经验。真正的数据资产需权属清晰、质量可靠、业务可用。数据资产管理不是IT项目,而是从业务出发的系统性变革,通过治理、盘货、运营、应用四层框架,让数据找得到、信得过、用得好。中小型企业也应轻量起步,聚焦核心指标,推动数据驱动文化,实现提效避坑。
|
Linux 数据库 iOS开发
CrossOver 25.1.0 for macOS & Linux - 领先的 Wine 解决方案
CrossOver 25.1.0 for macOS & Linux - 领先的 Wine 解决方案
672 0
|
弹性计算 运维 监控
【阿里云】操作系统控制台——体验与测评
阿里云操作系统控制台是一款强大的综合管理平台,集健康评估、智能诊断与性能优化于一体。通过可视化界面,用户可便捷高效地管理操作系统,降低运维复杂度。它支持弹性云服务器(ECS)的监控与调优,提供进程热点追踪、系统诊断等功能,帮助用户快速定位问题并给出优化建议。此外,控制台还具备地域限制和组件安装要求,需确保配置一致性。对于中小企业和技术新手,这款工具极大简化了运维流程,提升了资源利用率和系统稳定性。建议增加报告导出功能及内嵌智能助手,进一步优化用户体验。总结来说,该控制台如同“云服务器管家”,让运维更简单、业务更稳定。
|
存储 SQL 运维
当「内容科技企业」遇上多模数据库:新榜采用Lindorm打造全域数据“超级底盘”
新榜业务以数据服务提升内容产业信息流通效率,其数据处理需求聚焦于跨平台实时数据融合处理、实时分析检索、批量更新效率三大维度。Lindorm通过多模超融合架构,提供检索分析一体化、多引擎数据共享,分布式弹性扩展等能力,成为支撑新榜内容服务的核心引擎,助力客户在内容生态竞争中持续领跑。
|
人工智能 IDE 程序员
从 AI Coding 演进路径看通义灵码 AI 程序员的发布,让更多 idea 变成产品
从 AI Coding 演进路径看通义灵码 AI 程序员的发布,让更多 idea 变成产品
|
移动开发 API UED
|
缓存 IDE 开发工具
Arduino快速上手esp8266方案开发
Arduino快速上手esp8266方案开发
877 0
|
数据可视化 数据挖掘 数据库
空间单细胞|基于图像的数据分析(3)
空间单细胞|基于图像的数据分析(3)