魔幻的 2020 让我们怀疑人生是否存在最优解?我们某个时间的决策究竟是否正确?历史不能改变,但却会重演,我们究竟要从过去中学到什么呢?
让我们一起从动态规划中,来找寻这些问题的答案吧~
(咳咳,今天开始回归算法系列,来聊一聊之前的算法文章中没有讲到的内容。
什么是动态规划
动态规划(Dynamic Programic,简称 DP)是一种求解最优解的方法,它是一种特殊的分治思想,利用它可以实现时间复杂度的优化,有时也可以进行空间复杂度的优化,有时是需要更多的空间的(相比其他方法)。
dynamic 是动态的意思,也就是变化的,programing 可以理解为方程(我瞎说的),结合起来就是动态规划是用状态转移方程来求得最优解的算法。
在解释动态规划的时候,我们顺便理一理和它相关的两种思想——分治和贪心算法。
分治
分治是把大问题分解成若干个子问题,这样的能分解性质就是最优子结构的。
最简单的例子就是小明在解决问题 A 的时候,发现问题 A 是由问题 B 和 C 一起组成的,所以他想要解决问题 A,就需要把 B、C 一起去解决。
动态规划
动态规划是分治法的特例。
动态规划比分治法多了一种,就是重叠的子问题。
什么是重叠的子问题呢?举个例子来讲,可爱的小明遇到了一个可爱的问题,那就是问题 A,但是在前面需要解决一连串的问题,我们用A1,A2,A3,A4 ... A
来表示,在解决A1
之后会用它的解去解决类似的问题A2
, 然后再去解决A3
,最终再去解决 A,这就是重叠的子问题的典型代表。(下面的例题还会解释这个概念)
贪心
贪心比动态规划更加的特殊,它还需要问题满足另外一个性质——贪心选择性质,每次都可以把原问题分解成为一个子问题。
实际上再用动规的例子来说明贪心,在解决A1,A2,A3,A4 ... A
的时候,他发现解决不光有一种重叠子问题的性质在里面,更有趣的是,解决A1
需要一种特殊的规则。
例如小明现在在玩电脑游戏,而电脑游戏的最终目的是到达A
,而他又发现,只要一直往右边走就能到达最终的目的地了。这就是一种贪心的算法,在每次往右边走,就是一种特殊的规则,而走到目的地A
需要很多重复的子问题,也即每次活动一个单位。
入门
其实在很久之前我写的一篇文章中,以斐波那契数列这道基本题为例,详细阐述了从递归到 DP 的优化方法和思路,以及简单题的不简单的答法,大家不妨先去复习一下:
然后我们再来看看一般的动态规划解题思路。
解题思路
回到动态规划,这里有四个基本的概念:
- state(状态表示)
- function(转移方程)
- initial(初始化)
- final state(最终的状态)
在刚开始的时候,我们首先需要构建一个存储数据的表格,一般是数组或者矩阵,然后设定好每一个格子到下一个格子需要的转移方程。
然后去执行重复的步骤,从初始化的状态一直计算到最终需要的状态。