一篇文章带你学透动态规划背包问题
📅 2026/7/16 3:59:28
👁️ 次浏览
个人主页zephyr05个人专栏Linux C/C 竞赛专栏座右铭等风来不如追风去追寻的过程就是人生的意义。目录一、题目标准描述01背包完全背包二、例题解析01背包题目链接完全背包题目链接三、总结一、题目标准描述01背包核心特征每种物品只有一件可以选择放入或不放入不能拆分。标准题目描述有N件物品和一个容量为V的背包。每件物品只能使用一次。第i件物品的体积是v_i价值是w_i。求解将哪些物品装入背包可使这些物品的总体积不超过背包容量且总价值最大。输入/输出格式示例输入格式第一行两个整数NV分别表示物品数量和背包容积。接下来N行每行两个整数v_iw_i表示第i件物品的体积和价值。输出格式输出一个整数表示最大价值。数据范围0 N, V ≤ 10000 v_i, w_i ≤ 100完全背包核心特征每种物品都有无限件可用同一种物品可以多次选取。标准题目描述有N种物品和一个容量为V的背包每种物品都有无限件可用。第i种物品的体积是v_i价值是w_i。求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量且价值总和最大。输入/输出格式示例输入格式第一行两个整数NV分别表示物品数量和背包容积。接下来N行每行两个整数v_iw_i表示第i件物品的体积和价值。输出格式输出一个整数表示最大价值。数据范围0 N, V ≤ 10000 v_i, w_i ≤ 1000二、例题解析01背包题目链接确认状态表示dp[i][j]表示从前i个物品中挑选总体积不超过j此时的最大重量。状态转移方程答案返回dp[n][V]的值初始化循环范围i 从 1~nj 从 1~V代码class Solution { int dp[1010][1010]{0}; public: int knapsack(int V, int n, vectorvectorint vw) { for(int i1;in;i){ for(int j1;jV;j){ dp[i][j]dp[i-1][j]; if(jvw[i-1][0]) dp[i][j]max(dp[i-1][j],dp[i-1][j-vw[i-1][0]]vw[i-1][1]); //注意这里dp[i]对应的物品i在vw中的下标是i-1 } } return dp[n][V]; } };空间优化观察状态转移方程不难发现每一轮循环的dp[i]的值都依赖于上一轮的dp[i-1]的值既然如此我们可以采用滚动数组的方式将二维数组优化为一维数组。此时dp[j]的意义为i1时j从1到V最大重量i2时j从1到V最大重量 ... 以此类推外层循环i 从1到ndp[j]不断更新直到in时j从1到V最大重量。此时答案就是dp[V]。状态转移方程初始化dp[0]0循环范围特别要注意空间优化版本的j应该逆序循环因为根据状态转移方程dp[j]的更新依赖于dp[j-vw[i]]如果我们正序更新dp[j]的值那dp[j-vw[i]]就会先更新此时dp[j-vw[i]]的值就是考虑了第i个物品之后的值而我们需要的是只考虑前i-1个物品的dp[j-vw[i]]但是这个值已经被覆盖了。当我们更新dp[j]时第i个物品可能在dp[j-vw[i]]时就选择了一次在dp[j]时又可能被选择一次那最终的结果就会明显偏大。逆序循环就是为了先更新dp[j]再更新dp[j-vw[i]]。代码class Solution { int dp[1010]{0}; public: int knapsack(int V, int n, vectorvectorint vw) { for(int i1;in;i){ for(int jV;jvw[i-1][0];j--){ dp[j]max(dp[j],dp[j-vw[i-1][0]]vw[i-1][1]); } } return dp[V]; } };完全背包题目链接状态表示dp[i][j]表示从前i个面值的硬币中选总金额不超过j此时的最少硬币数。状态转移方程对比01背包其实唯一的区别的就是选择i的时候完全背包每件物品可以无限次选取所以还是dp[i][*]答案dp[n][amount]初始化j0时需要0个物品就可以达到要求i0 且j≠0时从0个物品中选择总金额达到j需要无限个物品。所以初始化数组的时候要给数组成员初始化一个很大的值。循环范围i 从 1~n j 从 1~amount代码class Solution { public: int coinChange(vectorint coins, int amount) { int ncoins.size(); vectorvectorint dp(n1,vectorint(amount1,10010)); for(int i1;in;i){ for(int j0;jamount;j){ if(j0) dp[i][j]0; else{ int valcoins[i-1]; dp[i][j]dp[i-1][j]; if(jval) dp[i][j]min(dp[i-1][j],dp[i][j-val]1); } } } return dp[n][amount] 10010 ? -1 : dp[n][amount]; } };空间优化和01背包同理利用滚动数组将二维数组优化为一维数组状态转移方程初始化dp[0]0循环范围注意完全背包j的循环顺序一定要正序循环刚好和01背包是反过来的因为物品可以无限次选取正序循环就可以满足这一点。代码class Solution { public: int coinChange(vectorint coins, int amount) { int ncoins.size(); vectorint dp(amount1,10010); dp[0]0; for(int i1;in;i){ for(int jcoins[i-1];jamount;j){ int valcoins[i-1]; dp[j]min(dp[j],dp[j-val]1); } } return dp[amount] 10010 ? -1 : dp[amount]; } };三、总结力扣上的背包问题很少会直接以“纯01背包”或“纯完全背包”的裸题形式出现更多时候它们被包装在各种应用题里需要你自己识别并转化为背包模型。因此死记硬背公式解法并不可取真正重要的是理解背包问题背后的核心原理掌握其思维范式——这样当遇到变形题目时你才能灵活地将它还原为熟悉的背包结构。在我看来背包问题乃至所有动态规划问题最大的难点都在于如何找到合适的状态表示。这种能力不是靠记住几个模板就能获得的它需要大量针对性的刷题训练在反复试错中逐渐培养出“题感”。算法学习远不止于刷题本身。每一次错误、每一回卡壳都是沉淀思考的契机。从错误中复盘在总结中提炼才能真正把知识内化。希望这篇梳理能帮你少走一些弯路更扎实地理解这两种基础背包算法的精髓。如果本文对你有帮助欢迎点赞、收藏、分享。如有疑问请在评论区留言我会尽力解答。博客首发于 CSDN转载请注明出处。
1. 分子指纹基础与RDKit实现分子指纹是化学信息学中用于表征分子结构的数字化方法,相当于给每个分子生成独特的"身份证号码"。想象一下,就像我们用指纹识别不同的人,分子指纹可以帮助计算机快速识别和比较不同的化合物。RDKit作为化…
📅 2026/7/16 3:59:28
1. 电路设计中的效率困境与突破方向作为一名电子工程师,我至今记得第一次独立设计电路时的狼狈场景。面对密密麻麻的元器件和错综复杂的连线,我整整花了三天时间才完成一个简单的放大电路设计。这种低效的工作状态在业内并不罕见——根据IEEE的调查数据显…
📅 2026/7/16 3:58:27
1. 先搞清楚英文分词到底要解决什么问题很多人一看到“英文分词”就觉得简单——不就是按空格切分吗?但实际处理文本数据时,你会发现远没这么简单。英文分词(Word Tokenization)的核心任务是把连续文本拆分成有意义的词汇单元&…
📅 2026/7/16 3:58:27
本文关键词:ai搜索优化geo靠谱么最近后台私信炸了,好多老板问同一个问题:现在搞那个AI搜索优化geo靠谱么?是不是又在割韭菜?说实话,刚听到这词儿的时候,我也愣了一下。毕竟这两年“AI”俩字被吹得太神,好像贴个标签就能躺赚流量。但作为在SEO圈摸爬滚打多年的老鸟,我得…
📅 2026/7/16 4:58:46
1. 项目概述:为什么用C面向对象重写线性表?线性表,数据结构课上的第一个“大魔王”,也是无数程序员面试时的“送分题”。但你真的理解它吗?或者说,当面试官让你手写一个线性表时,你脑海里浮现的…
📅 2026/7/16 4:58:49
1. 项目概述:从化学公式到C代码最近在整理一个化学动力学相关的数据处理项目时,我重新审视了“一级反应速率计算”这个看似基础但极其核心的模块。很多朋友,无论是化学、化工、生物还是材料专业的学生和工程师,在从理论公式转向实…
📅 2026/7/16 4:58:49
玩转Docker | 使用Docker部署file-transfer-go文件传输服务 前言 一、file-transfer-go项目介绍 项目简介 核心特性 二、系统要求 环境要求 环境检查 Docker版本检查 检查操作系统版本 三、部署file-transfer-go服务 下载Dashdot镜像 创建file-transfer-go容器 检查容器状态 检…
📅 2026/7/16 4:58:49
PyVista 是一个功能强大的 Python 库,专为科学计算中的 3D 可视化设计,基于 VTK(Visualization Toolkit)构建,但提供了更简洁、Pythonic 的 API。它广泛应用于地球科学、流体力学、结构力学、医学成像、计算几何等领域…
📅 2026/7/16 4:58:49
1. 从零开始理解C结构体:它到底是什么,以及为什么你需要它如果你刚开始学习C,在掌握了int、float、char这些基本数据类型之后,很快就会遇到一个瓶颈:现实世界的数据很少是孤零零存在的。比如,你想在程序里描…
📅 2026/7/16 4:58:49
1. 项目概述:为什么用遗传算法解5皇后问题,而不是直接回溯?我带过十几届算法课,也给不少初创团队做过AI架构咨询。每次讲到组合优化问题,学生和工程师的第一反应永远是“写个回溯试试”。这没错——55棋盘上找所有合法…
📅 2026/7/16 0:00:02
前几天调试一个简单的电源模块,用到了5.1V稳压管。电路接好,上电测试,万用表一量——输出居然只有4.7V。第一反应是稳压管坏了,换了一个新的,结果还是4.7V。这让我想起很多初学者都会遇到的困惑:明明标称5.…
📅 2026/7/16 0:00:02
1. 项目概述与核心价值 在高速数字系统、通信设备乃至精密测量仪器中,一个稳定、纯净且可精确调控的时钟信号,往往是整个系统稳定运行的“心跳”。无论是确保数据在光纤中无误传输,还是让ADC/DAC芯片精准采样,亦或是让多块FPGA板卡…
📅 2026/7/16 0:00:02
豆包openclaw最近圈子里都在聊豆包openclaw,我也没忍住,掏腰包入手了一套。说实话,刚拿到手的时候,心里是打鼓的。毕竟市面上类似的智能硬件太多了,有的吹得天花乱坠,用起来却是一堆bug。为了不让大家的钱打水漂,我连续用了半个月。从开箱到日常高频使用,甚至故意测试它…
📅 2026/7/15 22:51:06
SQLyog 13.3.1 社区版在Windows 10/11上的完整安装与连接指南 对于刚接触MySQL数据库管理的开发者和学生来说,选择一个直观易用的图形化管理工具至关重要。SQLyog作为一款轻量级但功能强大的MySQL GUI工具,能够显著提升数据库操作的效率和体验。本文将详…
📅 2026/7/15 19:03:10
SPEC CPU 2006 跨平台基准测试深度实战:ARM/X86/MIPS 架构配置优化与结果分析方法论在当今多元化的计算架构时代,如何客观评估不同处理器平台的真实性能成为系统工程师和性能优化专家的核心挑战。SPEC CPU 2006 作为业界公认的计算密集型基准测试套件&am…
📅 2026/7/15 14:09:20
目录
第一步:选对模板,省心一半
第二步:打开扫码点餐功能
开启功能按钮
桌台管理与桌码生成
第三步:个性化设计,打造品牌感
调整点餐页面
设置点餐规则 你还在让顾客站着排队点餐吗?2025年ÿ…
📅 2026/7/15 22:46:06
在业务中快速构建一个能理解私有文档、准确回答专业问题的智能助手,是很多开发团队面临的共同挑战。传统方案往往需要从零开始搭建复杂的 RAG(检索增强生成)系统,涉及文档解析、向量化、检索、大模型调用等多个环节,整…
📅 2026/7/16 4:59:31
FAE放射组学分析工具:医学影像特征探索的完整解决方案 【免费下载链接】FAE FeAture Explorer 项目地址: https://gitcode.com/gh_mirrors/fae/FAE
你是否曾经面对海量医学影像数据感到无从下手?想要从CT、MRI等影像中提取有价值的定量特征&#…
📅 2026/7/15 22:51:03