动态规划算法

解决问题

  • 动态规划基础问题
  • 背包问题
  • 打家劫舍问题
  • 股票问题
  • 子序列问题

贪心算法与动态规划算法

  • 贪心:局部最优推导全剧最优
  • 动态规划:由前(后)几个状态依次推导出其余状态

动态规划五部曲

  • 明确下标含义dp 数组含义
  • 递推公式
  • dp数组初始化
  • 遍历顺序
  • 打印 dp 数组

01背包问题:务必手动模拟

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

背包最大重量为4.

二维数组实现01背包

  • dp[ i ][ j ] 含义:[ 0, i ] 物品任取,存放容量为 j 的背包的最大价值
  • 递推公式:dp[ i ][ j ] = max( dp[ i - 1 ][ j ] , dp[ i - 1 ][ j - weight[ i ] ] + value [ i ] )
    - 不放物品 i :背包容量为 j , 所能装最大价值为 dp[ i - 1 ][ j ];
    - 放物品 i :背包容量为 j , 所能装最大价值为dp[ i - 1 ][ j - weight[ i ] ] + value [ i ];(背包容量倒退,直到可以留出空间给物品i )
  • 初始化:由递推公式可知,需要初始化 dp[ 0 ][ j ], dp[ i ][ 0 ];
    • dp[ 0 ][ j ] = value[ 0 ] ;
    • dp[ i ][ 0 ] = 0 ;
  • 遍历顺序:对于二维数组实现的01背包,两层 for 循环可以颠倒
    • 遍历物品(更好
    • 遍历背包

一维(滚动)数组实现01背包:滚动数组由二维数组压缩而来

  • dp[ j ] 含义:容量为 j 的背包的最大价值
  • 递推公式:dp[ j ] = max( dp[ j ] , dp[ j - weight[ i ] ] + value [ i ] )
    - 不放物品 i :背包容量为 j , 所能装最大价值为 dp[ j ];
    - 放物品 i :背包容量为 j , 所能装最大价值为dp[ j - weight[ i ] ] + value [ i ];
  • 初始化:dp 数组全部为 0
  • 遍历顺序:
    • 倒序:保证每个物品只添加一次。本质上还是对二维数组的遍历,并且右下角的值依赖于上一层左上角的值,因此需要保证左边的值仍然是上一层的,从右向左覆盖。
    • 先物品再背包

装满背包有多少种方法?

递归公式:dp[ j ] += nums[ j - nums[ i ] ];

完全背包理论基础

完全背包与01背包区别:

  • 01背包:每件物品使用1次:倒序
  • 完全背包:每件物品使用无数次:正序(纯完全背包问题下:物品与背包遍历顺序可以颠倒)

关键代码

// 先遍历物品,再遍历背包
for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = weight[i]; j <= bagWeight ; j++) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
}

组合与排列问题

  • 求组合:
    • 外层for:物品
    • 内层for:背包
  • 求排列:
    • 外层for:背包
    • 内层for:物品

动态规划基础问题

509. 斐波那契数

70. 爬楼梯

746. 使用最小花费爬楼梯

62. 不同路径

63. 不同路径 II

343. 整数拆分

  • dp数组极其下标含义:数 i 拆分后最大值为 dp[ i ]
  • 递归公式:dp[ i ] = max(dp [ i ], j * ( i - j ), j * dp[ i - j ] );
    • j * ( i - j )为拆为两数情况
    • j * dp[ i - j ]为拆为三数及以上情况
    • dp[i]为每轮保存最大值;

96. 不同的二叉搜索树

  • dp数组极其下标含义:由i个节点组成的不同二叉搜索树有dp[i]种
  • 递归公式:
  • dp[ i ] += dp[ j - 1 ] * dp[ i - j ];
    • dp[j - 1]为左子树种类
    • p[i - j]为右子树种类

背包问题

01背包问题

416. 分割等和子集

  • 难点:将问题抽象成01背包:元素不能重复使用——01背包
    • 物品:数组元素,物品重量 = 价值 = nums[i];
    • 背包容量:sum / 2;

1049. 最后一块石头的重量 II

  • 难点:将问题抽象成01背包:将数组分成两边,两边和越接近,越满足最后结果。同上题一样。

494. 目标和:dp[j] 代表装满背包有几种方法,区别于普通01背包求最大价值。

  • 难点:问题转化。将数组分成两部分,一部分为正数,一部分为负数。转化为背包问题。
  • dp[j]含义:装满容量为 j 的背包,有dp[j]种方法
  • 递推公式: dp[j] += dp[j - nums[i]];
  • 初始化: dp[0] = 1, 其余为 0.

474. 一和零

  • 难点:物品重量:两个维度0和1
  • dp[i][j]含义:i个0,j个1时,最大子集长度为 dp[i][j]
  • 递推公式:dp[i][j] = max(dp[i][j], dp[i - x][j - y] + 1);

完全背包问题

518. 零钱兑换 II

377. 组合总和 Ⅳ

link

link

link

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值