1、概述(Overview)
动态规划(Dynamic Programming)是一种求解决策过程(Decision Process)最优化的数学方法。它将一个复杂的问题分成相对简单的一类子问题,然后再将子问题分解成更加简单的一类子问题。在动态规划中,我们可以将每类子问题看成是动态规划的一个阶段。而在动态规划每个阶段中,往往会有很多状态(这也是为什么会说将一个复杂问题分成一类子问题,这些子问题之间具有共性,每个子问题就相当于该阶段下的一个状态),可以通过图1-1来加深理解这一概念。
在图1-1中,Problem表示我们目前遇到的问题, SPn−1m 表示在阶段 n−1 下第 m 个子问题。一般情况下,使用动态规划分析问题的时候都是使用自顶而下的分析方式,而在解决问题的时候却使用的是自下而上的方式。造成这样的区别在于当分析问题的时候,我们发现该问题其是由一类子问题组成的,解决这类子问题就可以解决当前问题。紧接着分析这类子问题时候,我们发现该类子问题又可以分为另外一类子问题,最终我们将找到不可再分的子问题。这相当于从金字塔的顶端走到了塔底,金字塔的每一层就相当于动态规划的每一个阶段(一类子问题)。在找到不可再分的子问题时后我们会恍然大悟,原来只有彻底解决了这类子问题,我们才能解决最终的问题。再拿金字塔举列,只有在建好金字塔的底层后一步步往上建,才能建成金字塔,走到金子塔的塔顶。世界上不会存在空中楼阁,金字塔建造过程就是我所说动态规划自下而上的解决过程。
2、阶段与状态(Phases and States)
在学习新知识的时候,我总是喜欢先在整体上了解我所要学的东西,这就相当于站在一个上帝的视角俯瞰世界一样。当我已在自己的脑海里为这一世界建立了轮廓之后,下面就要开始抽丝剥缕般去完善这个的世界。
在前一节我们已经了解了动态规划就是需要自顶而下的去分析问题且自下而上的去解决问题。而在这过程中,我引入的两个术语阶段 和状态可能会让你困惑,没关系,现在到我们去完善这两个概念的时候了。
相对于穷举法,动态规划的优势在于其将问题解决过程分成了阶段性的过程,且解决当前阶段的问题只需要获取之前某个阶段(一般情况下是上个阶段)解决问题的结果,更专业点的说法是获取当前阶段的状态只需要获取之前某个阶段的状态。而动态规划的难点主要就是去寻找阶段与阶段之间的联系。
拿Fibonacii数列举例:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144…
在生成Fibonacii数列的时候会发现,当前Fibonacci数是由前两个数相加获得。而生成新的Fibonacii数的过程就可以被认为是一个阶段,在每个阶段中,我们总需要获取上个阶段的结果,即该数的前两个数,因此我们可以认为每个阶段有两个状态。其实现过程如下
第0阶段
两个状态s0 = 0, s1 = 1第1阶段
产生新的输出 o =s0 + s1 = 0 + 1 = 1
两个状态 s0 = s1 = 1, s1 = o = 1第2阶段
产生新的输出o = s0 + s1 = 1 + 1 = 2
两个状态 s0 = s1 = 1, s1 = o = 2第3阶段
产生新的输出o =