一、什么是动态规划:
dynamic programming is a method for solving a complex problem by breaking
it down into a collection of simpler subproblems, solving each of those subproblems
just once, and storing their solutions - ideally, using a memory-based data structure.1
以上定义摘自维基百科
下面则是百度百科里的解释:
动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。
动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),
再合并子问题的解以得出原问题的解。通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量:一旦某个给
定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重
复子问题的数目关于输入的规模呈指数增长时特别有用。[^2]
由此,我们可以简略的概括下:“动态规划”通过把原来较复杂的问题递归的分解
为一组较简单的子问题,并通过存储每个子问题的解,使得每个子问题只计算一次就可以解决原问题的思想。
这里的某一类问题通常情况下是指某些最优化问题。这类问题可以有很多可行解,每个解都有一个值
,我们希望寻找具有最优值(最小值或最大值)的解。[^3]
一言以蔽之——“动态规划”是解决某类问题的方法(或思想而不是算法)
根据以上定义,很多人可能会觉得动态规划的真谛就是通过递归或递推,用额外的空间记录下已解决的子问题的解,
从而通过空间换时间来降低时间复杂度。其实不然,动态规划的本质是对每个阶段状态的定义以及当前状态与下一阶段*状态
关系*的定义(状态转移方程)。而所谓的“存储每个子问题的解”则是隐含的包含在状态关系里,那些“额外的记录空间”
则只是其表现形式而非其内涵。
二、什么是状态?什么是状态转移方程?
什么是状态?
我们先从最简单的Fibonacci数列谈起:
比如说我想计算第100个非波那契数,每一个非波那契数就是这个问题的一个状态,每求一个新数字只需要之前的两个状态。 <