当前位置: 首页 > article >正文

别再死记硬背背包问题公式了!用‘小偷逛博物馆’的故事带你手写递归C++代码

当小偷逛博物馆遇上背包问题用故事解锁递归思维推开厚重的博物馆大门昏暗的灯光下陈列着五件稀世珍宝。作为一名专业小偷你只有一个承重20公斤的背包每件藏品都有独特的重量和价值。如何在有限负重下最大化收益这个看似简单的选择困境恰恰是计算机科学中经典的背包问题。但今天我们不谈枯燥的数学公式而是用一场真实的盗窃行动来理解递归的精髓。1. 博物馆盗窃行动背包问题的现实映射想象你站在博物馆中央面前摆放着五件藏品藏品编号名称重量(kg)价值(万)1青铜方尊9102青花瓷瓶583玉雕观音454金丝唐卡345象牙印章23面对这些选择人类大脑会本能地采用贪心算法——先拿价值最高的。但很快你会发现问题青铜方尊虽然价值最高但占据了近一半的负重空间可能反而限制了总收益。这就是背包问题的核心矛盾——局部最优不等于全局最优。提示递归思维就像逆向规划盗窃路线从出口开始倒推每个决策点可能的结果。2. 递归小偷的决策树递归的核心在于分而治之。我们将大问题拆解为相同结构的小问题直到达到最小可解单元。对于背包问题每个决策点只有三种可能装不下当前藏品超重只能跳过装但不拿能装但选择不拿(可能为后续更高价值物品留空间)装且拿放入背包并承担重量减少的后果用C代码表示这个决策过程struct Artifact { int weight; int value; }; int steal(vectorArtifact artifacts, int capacity, int index) { if (index 0 || capacity 0) return 0; // 基线条件无物品或无容量 // 情况1当前物品超重只能跳过 if (artifacts[index].weight capacity) return steal(artifacts, capacity, index - 1); // 情况2和3比较拿与不拿的结果 int take artifacts[index].value steal(artifacts, capacity - artifacts[index].weight, index - 1); int leave steal(artifacts, capacity, index - 1); return max(take, leave); // 返回更优选择 }这段代码完美再现了小偷的思考过程。每次递归调用都是一个新的决策点而max(take, leave)则体现了择优录取的盗窃哲学。3. 递归栈盗窃行动的记忆回放理解递归最难的部分是调用栈的运作。让我们用博物馆监控回放的方式可视化这个过程初始状态背包空置(20kg)面对所有5件藏品第一层决策考虑是否拿青铜方尊(9kg/10万)拿剩余11kg面对剩余4件不拿仍20kg面对剩余4件第二层决策每种选择又分裂出新的可能性...拿青花瓷瓶(5kg/8万)或不拿以此类推...这个过程形成的决策树如下开始(20kg) ├─ 拿方尊(剩余11kg) │ ├─ 拿瓷瓶(剩余6kg) │ │ ├─ 拿玉雕(剩余2kg) │ │ │ ├─ 拿唐卡(超重) │ │ │ └─ 不拿唐卡 │ │ └─ 不拿玉雕 │ └─ 不拿瓷瓶 └─ 不拿方尊 ├─ 拿瓷瓶(剩余15kg) └─ 不拿瓷瓶每个分支最终都会到达基线条件(index 0)这时就可以比较各路径的总价值了。4. 优化策略聪明小偷的剪枝技巧原始递归存在大量重复计算。比如拿方尊→不拿瓷瓶和不拿方尊→拿瓷瓶可能在剩余重量相同时重复计算相同子问题。我们可以用记忆化(memoization)优化unordered_mapstring, int memo; // 用哈希表存储已计算结果 int stealWithMemo(vectorArtifact artifacts, int capacity, int index) { string key to_string(index) , to_string(capacity); if (memo.count(key)) return memo[key]; if (index 0 || capacity 0) return 0; if (artifacts[index].weight capacity) { memo[key] stealWithMemo(artifacts, capacity, index - 1); return memo[key]; } int take artifacts[index].value stealWithMemo(artifacts, capacity - artifacts[index].weight, index - 1); int leave stealWithMemo(artifacts, capacity, index - 1); memo[key] max(take, leave); return memo[key]; }这种优化将时间复杂度从O(2^n)降低到O(n*W)其中n是物品数量W是背包容量。就像经验丰富的小偷会记住哪些展柜组合最有利可图。5. 从递归到动态规划盗窃大师的进阶之路递归虽然直观但存在栈溢出风险。动态规划(DP)提供了更高效的迭代解法其核心是构建一个决策表int dpSteal(vectorArtifact artifacts, int capacity) { vectorvectorint dp(artifacts.size()1, vectorint(capacity1, 0)); for (int i 1; i artifacts.size(); i) { for (int w 1; w capacity; w) { if (artifacts[i-1].weight w) { dp[i][w] dp[i-1][w]; } else { dp[i][w] max(dp[i-1][w], artifacts[i-1].value dp[i-1][w-artifacts[i-1].weight]); } } } return dp[artifacts.size()][capacity]; }这个DP表就像小偷的作案计划书系统地记录了在不同剩余容量下面对前i件物品时的最优选择。从空包开始逐步填充最终右下角的值就是全局最优解。6. 实战演练破解博物馆安防系统让我们用完整代码模拟这次盗窃行动#include iostream #include vector #include unordered_map using namespace std; struct Artifact { string name; int weight; int value; }; void printChoice(const vectorArtifact artifacts, const vectorvectorint dp) { int i artifacts.size(); int w dp[0].size() - 1; vectorstring chosen; while (i 0 w 0) { if (dp[i][w] ! dp[i-1][w]) { chosen.push_back(artifacts[i-1].name); w - artifacts[i-1].weight; } i--; } cout 最优选择方案; for (auto item : chosen) cout item ; cout \n总价值 dp[artifacts.size()][dp[0].size()-1] 万\n; } int main() { vectorArtifact artifacts { {青铜方尊, 9, 10}, {青花瓷瓶, 5, 8}, {玉雕观音, 4, 5}, {金丝唐卡, 3, 4}, {象牙印章, 2, 3} }; int capacity 20; vectorvectorint dp(artifacts.size()1, vectorint(capacity1, 0)); for (int i 1; i artifacts.size(); i) { for (int w 1; w capacity; w) { if (artifacts[i-1].weight w) { dp[i][w] dp[i-1][w]; } else { dp[i][w] max(dp[i-1][w], artifacts[i-1].value dp[i-1][w-artifacts[i-1].weight]); } } } printChoice(artifacts, dp); return 0; }运行结果会显示最优选择是拿青铜方尊(9kg/10万)、青花瓷瓶(5kg/8万)和象牙印章(2kg/3万)总重16kg总价值21万。有趣的是这个方案没有用完全部20kg容量说明在算法世界里有时留白反而是最优策略。

相关文章:

别再死记硬背背包问题公式了!用‘小偷逛博物馆’的故事带你手写递归C++代码

当小偷逛博物馆遇上背包问题:用故事解锁递归思维 推开厚重的博物馆大门,昏暗的灯光下陈列着五件稀世珍宝。作为一名"专业"小偷,你只有一个承重20公斤的背包,每件藏品都有独特的重量和价值。如何在有限负重下最大化收益&…...

模糊聚类实战:用传递闭包法给教师教学质量打分,附Python完整代码

模糊聚类实战:用传递闭包法给教师教学质量打分 教育评价从来不是非黑即白的判断题。当我们试图对教师的教学质量进行分类时,传统的硬性划分方法往往掩盖了教师能力之间的渐变与过渡。四位教师在师德师表、教学过程等五项指标上的评分差异,可能…...

SEO关键词查询工具哪个好_SEO工具的使用成本是多少

SEO关键词查询工具哪个好_SEO工具的使用成本是多少 在当今数字化时代,优化网站的搜索引擎表现(SEO)已经成为每一个企业和网站运营者必不可少的一部分。其中,关键词查询工具是SEO工作中不可或缺的一环。在众多的SEO工具中&#xf…...

OpenClaw视频处理流水线:千问3.5-9B自动剪辑与字幕生成

OpenClaw视频处理流水线:千问3.5-9B自动剪辑与字幕生成 1. 从手动剪辑到AI流水线的转变 去年夏天,当我需要为一期技术教程视频添加字幕时,整整花了三个小时反复校对时间轴。这种低效的重复劳动让我开始思考:能否用AI实现视频处理…...

从Python代码到动态仿真:手把手教你用SimPy搭建第一个系统动力学模型

从Python代码到动态仿真:手把手教你用SimPy搭建第一个系统动力学模型 在数据分析与人工智能项目中,系统动力学(System Dynamics)正逐渐成为分析复杂系统行为的重要工具。与传统的Vensim等专用软件不同,Python开发者可以…...

图像去雾新突破:DEConv和CGA如何提升自动驾驶视觉系统性能

图像去雾新突破:DEConv和CGA如何提升自动驾驶视觉系统性能 清晨的浓雾中,一辆自动驾驶汽车缓缓驶过十字路口。车载摄像头捕捉到的画面本该模糊不清,但屏幕上却清晰地显示着行人、信号灯和障碍物——这背后是DEA-Net图像去雾技术创造的奇迹。在…...

HALCON开发避坑指南:解决SetWindowParam报错#5190的3种方法(附hcanvas.dll文件)

HALCON开发实战:彻底解决SetWindowParam报错#5190的深度解析 在工业视觉开发领域,HALCON作为行业标杆工具链,其窗口管理系统一直是实现高效图像处理的关键组件。但当你在Visual Studio中满怀信心地调用SetWindowParam进行窗口参数配置时&…...

Matlab处理遥感影像必看:地理坐标和投影坐标的GeoTIFF读写,别再搞混了!

Matlab遥感影像处理实战:地理坐标与投影坐标的GeoTIFF读写全解析 遥感影像处理中,坐标系的选择与正确读写是许多初学者容易踩坑的环节。今天我们就来深入探讨Matlab环境下如何处理这两种不同坐标系的GeoTIFF文件,从原理到实践,帮你…...

微信小程序物流查询插件接入全攻略:从资质申请到waybill_token获取(附完整代码)

微信小程序物流查询插件深度接入指南:全流程解析与实战代码 最近在帮一个电商客户优化小程序时,发现物流查询功能直接影响了30%的用户留存率。微信官方提供的物流查询插件确实能解决这个问题,但接入过程中遇到的坑比想象中多得多。今天就把完…...

树莓派5硬件PWM驱动舵机实战:从设备树编译到精准角度控制

树莓派5硬件PWM驱动舵机实战:从设备树编译到精准角度控制 树莓派5作为一款高性能的单板计算机,其硬件PWM功能在机器人、机械臂和模型制作等领域具有广泛的应用前景。与软件PWM相比,硬件PWM能够提供更稳定、更精确的控制信号,特别是…...

别再瞎调参了!HuggingFace Trainer微调BERT/ViT的保姆级避坑指南(附ArcFace实战代码)

HuggingFace Trainer微调实战:从参数陷阱到模型优化的深度拆解 当你第5次看到验证集准确率在0.85附近震荡不前,而训练损失仍在持续下降时,是否开始怀疑自己选择的优化器、学习率或损失函数?这不是个例——超过60%的NLP工程师在使用…...

FPGA图像处理避坑指南:实现CLAHE时,你的直方图统计与插值模块可能踩的这些雷

FPGA图像处理避坑指南:CLAHE实现中的直方图统计与插值模块陷阱解析 第一次在FPGA上实现CLAHE算法时,我盯着屏幕上那些奇怪的边界伪影和忽明忽暗的色块,整整三天没想明白问题出在哪。直到把示波器接到开发板上,才发现直方图统计模块…...

星图GPU云体验OpenClaw:免安装调试Phi-3-mini-128k-instruct镜像

星图GPU云体验OpenClaw:免安装调试Phi-3-mini-128k-instruct镜像 1. 为什么选择云端体验OpenClaw 上周我尝试在本地笔记本上部署OpenClaw时,被各种环境依赖和权限问题折磨得够呛。正当我准备放弃时,偶然发现星图平台提供了预装OpenClaw的GP…...

从零开始:手把手教你用UML绘制状态图(附实战案例)

从零开始:手把手教你用UML绘制状态图(附实战案例) 在软件开发的世界里,UML(统一建模语言)就像工程师的通用语言,而状态图则是其中最强大的工具之一。想象一下,当你需要清晰地描述一个…...

如何利用Lv值实现三级降帧

目录 一、核心逻辑( 二、5 种帧率 → 精简为 3 级 三、LV 阈值划分 四、代码实现 一、核心逻辑 亮度越暗 → LV 越小 → 帧率越低亮度越亮 → LV 越大 → 帧率越高 三级降帧就是: 高亮度:高帧率(30fps)中亮度&am…...

OpenClaw技能市场探秘:Phi-3-vision支持的十大实用插件

OpenClaw技能市场探秘:Phi-3-vision支持的十大实用插件 1. 为什么需要关注OpenClaw技能市场? 作为一个长期在自动化工具领域折腾的技术爱好者,我最初接触OpenClaw时,最吸引我的不是它的基础框架,而是它那个充满可能性…...

CSS如何实现不同尺寸的卡片网格_利用Grid跨行跨列设置

Grid卡片跨行跨列需用grid-row: span 2等语法避免线号计算错误;auto-fit需容器有明确宽度;高度不一致时宜用嵌套布局或grid-auto-rows: auto;IE11不支持现代Grid跨行,应降级方案。Grid卡片跨行跨列时,grid-row和grid-c…...

【安全心法】别用定时器喂狗!撕碎看门狗的伪安全面具,直面“僵尸系统”的物理绞肉机

摘要:在硬实时控制系统中,硬件看门狗被奉为防止系统死机的终极神明。但无数软硬件工程师出于偷懒或对底层架构的无知,将“喂狗”动作外包给了高频的定时器中断或最高优先级的独立任务。本文将彻底摒弃代码,纯粹从系统架构的安全哲…...

【时域心法】别用“平滑”谋杀你的闭环!撕碎软件滤波的视觉骗局,直视“相位延迟”的物理死刑

摘要:纯软件思维有着一种对“平滑数据”的病态迷恋。当他们看到夹杂着毛刺和电磁噪声的 ADC 信号时,最本能的反应就是砸下极其粗暴的“滑动平均滤波”或“低通滤波”。他们在上位机屏幕上画出了绝美的平滑曲线,却不知道自己已经亲手切断了系统…...

QW_Sensors嵌入式传感器驱动库详解

1. QW_Sensors 库概述QW_Sensors 是一个面向硬件开发者的轻量级嵌入式传感器驱动库,专为 QW Shield 硬件平台设计。该库并非通用型多平台抽象层,而是深度耦合于 QW Shield 的物理布局、供电逻辑、通信拓扑与固件约束,其核心价值在于将底层硬件…...

BUCK变换器断续模式实战:从公式推导到MATLAB仿真验证(附代码)

BUCK变换器断续模式实战:从公式推导到MATLAB仿真验证(附代码) 在电力电子领域,BUCK变换器作为最基础的降压型拓扑结构,其工作模式的理解直接影响着电源设计的可靠性。许多初学者往往对断续模式(DCM)的特性感到困惑——…...

1985-2025年全国省/市/区县土地利用分类面积及占比统计数据

数据介绍 全国土地利用分类面积统计数据(1985-2025) 数据简介 本数据集基于1985-2025年30米分辨率土地利用分类数据,结合行政区划边界,提供全国省、市、县三级行政单元的土地利用分类面积及占比统计,为土地利用变化…...

ANDON系统赋能自行车制造实现异常闭环管理

传统自行车制造业面临着多工位协同效率低、异常响应滞后等痛点。以某自行车制造工厂为例,其生产线涵盖车架组装、轮组调试、整车检测等多环节,传统异常管理存在响应滞后、协同混乱、数据缺失三大瓶颈。引入ANDON系统后,通过构建“工位触发-网…...

SEO排名推广软件有哪些技巧

SEO排名推广软件有哪些技巧 在当今互联网时代,搜索引擎优化(SEO)已经成为了各种企业和个人网站提升流量和业务的重要手段。其中,SEO排名推广软件能够帮助用户更加高效地实现网站的优化和推广。SEO排名推广软件有哪些技巧呢&#…...

Telemetrix4UnoR4:Arduino Uno R4的轻量级双向固件框架

1. 项目概述Telemetrix4UnoR4 是专为 Arduino Uno R4 系列开发板设计的嵌入式固件服务器框架,其核心目标是构建一个轻量、可靠、可扩展的双向通信桥梁,使 Python 主机端(运行telemetrix_uno_r4或telemetrix_uno_r4-aio库)能够以类…...

ArcGIS Pro新手必看:用‘按掩膜提取’和‘裁剪’工具搞定栅格与矢量数据范围限定(附详细步骤图)

ArcGIS Pro数据范围限定实战:从工具选择到避坑指南 刚接触ArcGIS Pro的研究人员常常会遇到这样的困惑:手头收集了研究区域的各种数据,却不知道如何精确限定到自己的研究范围。面对"裁剪"和"按掩膜提取"两个看似相似的工具…...

PyTorch 3.0静态图分布式训练落地实录:从torch.compile到DistributedGraphExecutor的7个关键配置节点

第一章:PyTorch 3.0静态图分布式训练全景概览PyTorch 3.0 引入了原生静态图编译能力(TorchDynamo Inductor 后端深度集成),结合 torch.distributed 的增强型 API,构建出面向大规模集群的高性能分布式训练范式。与传统…...

numpy+pandas核心操作全总结:详细代码注释(数组/Series/DataFrame完整指南)

📢 更多数据分析干货,关注公众号:船长Talk,每天分享 Python/SQL 实战技巧!两个重要的包:numpy、pandas,是数据分析师的必备基础。本文做全面总结,每段代码都有详细注释,建…...

【STM32HAL库实战】从零构建外部中断:按键唤醒与事件响应

1. 外部中断基础与STM32应用场景 第一次接触STM32外部中断时,我盯着原理图上的按键发呆了半小时——明明GPIO轮询检测就能实现的功能,为什么非要大费周章配置中断?直到某个深夜调试项目时,才真正体会到中断机制的精妙之处。当时我…...

鸿子铭:电脑上录视频后出现这个电流声得怎么处理?

大家好,我是鸿子铭。可能我们在电脑上做视频的时候可能会电流声,或者说我们在录视频之后,它也会出现这个沙沙这个声音。出现这个问题,我们该如何去解决呢?其实解决的方法有两点,在电脑上只要调试这两点的话…...