动态规划总结

时间:2024-04-16 07:25:14

一、动态规划演化

对于一个问题,如果我们能够将最大的问题,分解为几个子问题,然后通过选择连接大问题和子问题

然后子问题可以这样继续分解,那么,就意味着可以使用动态规划进行求解

1.使用递归进行求解

由于每个子问题形式相同,我们使用递归进行求解,直到递归到最小的子问题就返回

2.通过备忘录去重 

直接递归复杂度太高,我们一般使用一个memo数组进行去重

3.写为dp数组迭代形式

返回条件就是初始值,转移方程照搬写为dp形式

二、动态规划思路 

1.状态表示 

有些题以-1为空,有些题以0为空,这是不同写法的缘故

因为dp迭代写法是由递归推出来的,而递归中i可以为-1,因此很多时候转换为dp后就沿用了(这些题一般不需要考虑空这种情况)

但是,有些题需要从空开始考虑,但是dp数组索引只能0开始,那么就需要手动调整+1,dp[0]就变成了空

这个一定注意,不然越看越昏 

2.初始化 

以一维为例,多维同理 

1.求方案数

求方案数的时候,空背包装空物品表示可以装一次,因此dp[0] = 1

2.最优路径

在求单条路径上的最优值时,空背包中也能装空物品,但是由于是空物品,什么属性都没有,因此dp[0] =0

3.转移方程

1.求方案数

转移方程常常为dp[i] + dp[j]的形式(加法原理)

2.最优路径(以路径上一个参数为指标)

 转移方程通常为max/min(dp[i],dp[j])的形式

3.从做选择理解转移方程 

转移方程的本质就是做选择

背包问题中,我们的选择是对某一个物品,取还是不取

单子序列问题中,我们的选择是,对上一个元素(要求连续),或者前i个元素(求不连续的子序列)中进行

双序列问题中,我们的选择是,选择那条序列的指针向后移动,移动到dp[i][j]

(注意,如果是子序列问题,不能对子序列进行选择,具体理由线性dp相应章节有红字解释)

在打家劫舍问题中,我们的选择是今天是否抢劫

在股票买卖问题中,我们的选择是今天是买、卖还是不作为

 4.遍历方式

1.比较在意顺序的问题

背包问题中,如果我们不在意不同路径结果的顺序(元素相同,顺序不同视为重复),那么 遍历方式先背包和先物品一样

但是,如果我们需要考虑不同路径的顺序,那么我们需要先物品后背包

具体细节参考背包问题博客

2.不太在意顺序的问题

除背包问题外,其他问题似乎都不太在意顺序问题,单序列,打家劫舍,股票问题等问题,由于是一维,不需要考虑顺序,而双序列中两条序列等价,就算是处理子序列问题,顺序也是可以颠倒的

这类问题的遍历一般参照,先进行dp[i][j]的下标遍历,然后进行选择遍历