分治法就先这么说完了,其实本质上求子问题,但求解子问题时若分解的问题太多又重复,消耗时间太多也不是个事吧。接下来讲的算法思想也是求解子问题,不过在求解子问题的过程上却要比分治法精明得多。
1、基本思想
动态规划特别适用于需要重复求解子问题的问题,基本思想就是用一个表之类的数据结构来记录子问题的答案。
说得学术一点,只有问题具有最优子结构和重叠子问题就可以使用动态规划来加快求解的过程。
最优子结构:问题的最优解包含子问题的最优解。
重叠子问题:子问题重复计算。
所以我们在开始运用动态规划时就有清晰的4个步骤:
①找出问题的解的最优子结构性质,这个解往往有最优的意思,并刻画其结构特征以便下一步定义最优值。
②通过问题与其子问题的递归关系定义最优值。
③以自底向上的方式计算出最优值。
④若有必要根据计算最优值时得到的信息,构造最优解。
2、实例
碎嘴了这么多,我们又拿出Fibonacci数列的例子来看看动态规划相比分治法的优点。
按照Fibonacci数列的递归式F(n)=F(n-1)+F(n-2),我们所要求的子问题为F(n-1)=F(n-2)+F(n-3),很明显F(n-2)就重复计算了一次。可想而知,从F(n-2)到F(3)都是反复计算的子问题。动态规划就是反着过来,依次求解F(3)、F(4)、F(5)...直到F(n),这样就一点都不浪费时间地计算出了第n个Fibonacci数。
fib
虽然这个问题过于简单,没有必要依步骤来,但清晰的步骤是良好的习惯。
3、延伸
动态规划不仅仅在计算机科学当中使用,在运筹学上也有涉及,经济学上也有许多相关的模型。也就是说,面对状态变化频繁、并且需要有对应控制的问题都可以用动态规划来解决问题。动态规划真是一个好算法。