动态规划(3)——算法导论(18)

1. 写在前面

咱们已经用动态规划的方法解决了两个问题,但可能仍是弄不清应该在什么时候使用动态规划。本篇,咱们对动态规划方法作一个总结,重点关注适合应用动态规划方法求解的最优化问题应该具有的两个要素:最优子结构子问题重叠html

2. 最优子结构

用动态规划方法求解最优化问题的第一步就是刻画最优解的结构。如以前的两个问题算法

若是一个问题的最优解包含其子问题的最优解,咱们就称此问题具备最优子结构性质。app

固然,具备最优子结构性质只是判断一个问题是否适用动态规划方法的一个很好的线索,它也可能适用于贪心策略函数

回顾咱们以前的两个问题。在钢条切割问题中,咱们观察到,长度为n的钢条的最优切割方案是由第一次切割后(若是最优方案须要切割)获得的两端钢条的最优切割方案组成的;在矩阵乘法链问题中,咱们一样看到,优化

\[ A_iA_{i+1}...A_j的最优括号化方案首先在A_k和A_{k+1}中之间进行划分,而后对A_iA_{i+1}...A_k和A_{k+1}A_{k+2}...A_j继续进行最优括号化 \]spa

咱们发现,在发掘最优子结构性质的过程当中,实际遵循了以下的通用模式:htm

  1. 证实问题最优解的第一个组成部分是作出了一个选择。例如,选择钢条第一次切割的位置,选择矩阵链的划分位置。作出此次选择会产生一个或多个待解的子问题。blog

  2. 对于一个给定的问题,在其可能的第一步选择中,咱们假定已经知道哪一种选择才会获得最优解。可是咱们并不关心这种选择具体是如何获得的,只是假定已经知道了这种选择。递归

  3. 给定可得到最优解的选择后,你肯定此次选择会产生哪些子问题,以及如何最好的刻画子问题空间。get

  4. 利用剪切—粘贴(cut-and-parse)技术证实:做为构成原问题最优解的组成部分,每一个子问题的解就是它自己的最优解。利用反证法能够证实:假设子问题的解不是其自身的最优解,那么咱们就能够从原问题的解中“剪切”掉这些非最优解,将最优解“粘贴”进去,从而获得原问题一个更优的解,这与最初的解是原问题的最优解相矛盾。

一个刻画子问题空间的好经验是:保持子问题空间尽量简单,但在必要时才扩展它。例如,在求解钢条切割问题时,子问题空间中包含的问题为:对每一个i值,长度为i的钢条的最优切割问题。这个子问题空间已经很通常了。

对于动态规划问题,咱们还须要注意的两个方面是:

  1. 原问题的最优解中,涉及多少个子问题;
  2. 在肯定最优解使用哪些子问题时,咱们须要考察多少种选择。

例如,在钢条切割问题中,长度为n的钢条的最优切割方案仅仅使用一个子问题(长度为n-i的钢条的最优切割问题),但咱们必须考察i的n种不一样的取值,来肯定哪个会产生最优解。

再好比,在矩阵链乘法问题中,最优解使用了两个子问题,须要考察j-i种状况。

之因此须要注意上述两个方面,是由于咱们能够用来它来粗略的计算动态规划算法的时间效率。对于钢条切割问题,共有Θ(n)个子问题,每一个子问题最多须要考察n种选择,所以运行时间为O(n^2)。矩阵链乘法问题共有Θ(n^2)个子问题,每一个子问题最多须要考察n-1中选择,所以运行时间为O(n^3)。

3. 子问题重叠

适合用动态规划问题方法求解的最优化问题应该具有的第二个性质是子问题空间必须足够“小”,即问题的递归算法会反复地求解相同的子问题,而不是一直生成新的子问题。通常来讲,不一样的子问题的总数是输入规模的多项式函数为好。

若是递归算法反复求解相同的子问题,咱们就称最优化问题具备折叠子问题(overlapping)性质。

动态规划算法一般是采用“备忘录”来利用该性质:对每一个子问题求解一次,将解存入“备忘录”中;当再次须要这个子问题时直接查表,这样可保证再次求解相同问题时,只须要花费常量时间。

这里就再也不举例说明,可参见钢条切割问题矩阵乘法链问题

相关文章
相关标签/搜索