news 2026/7/4 17:42:30

动态规划的解题步骤

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
动态规划的解题步骤

状态转移公式(递推公式)是很重要,但动规不仅仅只有递推公式。

对于动态规划问题,可以拆解为如下五步曲:

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

01背包问题

题目描述:有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。

每一件物品其实只有两个状态,取或者不取,所以可以使用回溯法搜索出所有的情况,那么时间复杂度就是$o(2^n)$,这里的n表示物品数量。

所以暴力的解法是指数级别的时间复杂度。进而才需要动态规划的解法来进行优化!

举一个例子:背包最大重量为4。

物品为:

重量价值
物品0115
物品1320
物品2430

问背包能背的物品最大价值是多少?

二维dp数组

  1. 确定dp数组以及下标的含义

对于背包问题,有一种写法, 是使用二维数组,即dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少

  1. 确定递推公式

再回顾一下dp[i][j]]的含义:从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。

那么可以有两个方向推出来dp[i][j],

  • 不放物品i:由dp[i - 1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j]。(其实就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以背包内的价值依然和前面相同。)
  • 放物品i:由dp[i - 1][j - weight[i]]推出,dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值

所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

  1. dp数组如何初始化

关于初始化,一定要和dp数组的定义吻合,否则到递推公式的时候就会越来越乱

首先从dp[i][j]的定义出发,如果背包容量j为0的话,即dp[i][0],无论是选取哪些物品,背包价值总和一定为0。如图:

在看其他情况。

状态转移方程 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 可以看出i 是由 i-1 推导出来,那么i为0的时候就一定要初始化。

dp[0][j],即:i为0,存放编号0的物品的时候,各个容量的背包所能存放的最大价值。

那么很明显当 j < weight[0]的时候,dp[0][j] 应该是 0,因为背包容量比编号0的物品重量还小。

当j >= weight[0]时,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品。

代码初始化如下:

java

for (int j = 0 ; j < weight[0]; j++) { // 当然这一步,如果把dp数组预先初始化为0了,这一步就可以省略,但很多同学应该没有想清楚这一点。 dp[0][j] = 0; } // 正序遍历 for (int j = weight[0]; j <= bagweight; j++) { dp[0][j] = value[0]; }

此时dp数组初始化情况如图所示:

dp[0][j] 和 dp[i][0] 都已经初始化了,那么其他下标应该初始化多少呢?

其实从递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 可以看出dp[i][j] 是由左上方数值推导出来了,那么 其他下标初始为什么数值都可以,因为都会被覆盖。

初始-1,初始-2,初始100,都可以!

但只不过一开始就统一把dp数组统一初始为0,更方便一些。如图:

  1. 确定遍历顺序

在如下图中,可以看出,有两个遍历的维度:物品与背包重量

那么问题来了,先遍历 物品还是先遍历背包重量呢?

其实都可以!! 但是先遍历物品更好理解

理解递归的本质和递推的方向

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

.NET金融数据集成解决方案:YahooFinanceApi 深度解析与实战指南

.NET金融数据集成解决方案&#xff1a;YahooFinanceApi 深度解析与实战指南 【免费下载链接】YahooFinanceApi A handy Yahoo! Finance api wrapper, based on .NET Standard 2.0 项目地址: https://gitcode.com/gh_mirrors/ya/YahooFinanceApi 在金融科技应用开发中&am…

作者头像 李华
网站建设 2026/6/30 23:46:48

重大消息!!2026年荆门中级职称申报即将开始,附上申报详细攻略

&#x1f4e3;荆门今年职称申报比去年提前了一个月&#xff0c;今天本篇文章我就详细给大家说明一下今年荆门职称怎么申报&#xff1f;有哪些要求&#xff1f;什么时候申报呢&#xff1f;想知道的一起来看看吧~~一、2026年荆门中级职称申报时间&#xff1a;&#xff08;正式网上…

作者头像 李华
网站建设 2026/6/30 23:45:08

别再凭感觉选RC了!用这个比率设计法,5分钟搞定Sallen-Key低通滤波器

别再凭感觉选RC了&#xff01;用比率设计法5分钟搞定Sallen-Key低通滤波器在模电实验室里&#xff0c;最令人抓狂的时刻莫过于看着仿真完美的滤波器电路&#xff0c;换上实际元件后却变成了一团糟的波形。去年调试心电监测设备时&#xff0c;我曾用整整三天时间反复调整一个截止…

作者头像 李华
网站建设 2026/6/30 23:40:22

使用Capacitor将网页游戏封装为Android手机APP的完整实战记录

一、为什么要写这篇博客&#xff1f; 今天花了一整天时间&#xff0c;成功将一个基于HTML5/Canvas开发的网页游戏&#xff08;星球专注飞行&#xff09;封装成了一个可以在安卓手机上直接安装运行的 .apk 文件。 作为一个从未接触过Android开发的前端开发者&#xff0c;整个过…

作者头像 李华