动态规划算法的经典思路讲解,详见文章:
https://labuladong.gitbook.io/algo/di-ling-zhang-bi-du-xi-lie/dong-tai-gui-hua-xiang-jie-jin-jie
动态规划算法的一般适用范围为具有最优子结构和存在重叠子问题。通常来说解决问题的核心思想就是穷举,而穷举的过程中我们发现会重复计算多个同样的子问题分支,基于以上过程,我们在第一次计算dp的过程中,会使用额外的数组空间存储第一次计算到的结果值。当然这个存储结构也不一定非要是数组,哈希表(c++中unordered_map)也可以。是否取用哈希表还得看具体问题的数据是否连贯,即取用到某个数组的下标值,其对应访问数组中的值,就是该子问题的解。
该类算法题目,通用法则为:
1.建立状态转移方程
在该步中我们可以模拟,我们处在某个状态,可以做出什么样的选择,从而进入到下一状态。
说暴力点也就是,我们需要穷举有限个状态,对每个状态做出相应的选择从而使其进入下一状态。
伪代码类似以下操作。
# 初始化
base casedp[0][0][...] = base
# 进行状态转移
for 状态1 in 状态1的所有取值:
for 状态2 in 状态2的所有取值:
for ...
dp[状态1][状态2][...] = 求最值(选择1,选择2...)
2.在确定好状态转移方程后,设定初始条件,设定好缓存的数据结构,以及每个下标代表的含义,以及各个下标确认好后对应的状态。
3.进行迭代或者递归,如果有相应的结果那么直接使用,如果没有缓存计算后的结果。即缓存并复用以往的结果。
一般来说,迭代法是从底向上去计算并缓存结果的,递归法是从上向下去计算并缓存结果的。
多数问题的时间复杂度,迭代法更占优,也就是迭代法的时间复杂度通常会被递归法要低一些。
当然也不是全部,具体问题具体分析,是选用从上而下的递归法还是从下而上的迭代法,完全取决于代码书写的难度和具体性能的提升。