动态规划的描述与分析方法——《算法导论》

来源:互联网 发布:非主流 知乎 编辑:程序博客网 时间:2024/06/05 21:04

背景:

动态规划是一个很难的算法,以我近些日子做的动态规划的题目来看,十个里面有八个我是想不出来是怎么做的,因为有许多问题需要思考它的递推式,而我那么笨,就是找不到解决此问题的方法,所以我要系统地理论性地将《算法导论》中的动态规划的分析方法整理出来,以便以后做题时能够合理分析此问题。


动态规划描述:

它应用于子问题重叠的情况,即不同的子问题具有公共的子子问题(子问题的求解是递归进行的,将其划分为更小的子子问题)。动态规划算法对每个子子问题只求解一次,将其保存在一个表格中,这样以后就无需再重新求解已经解决好的子子问题。

动态规划求解的问题:最优化问题,比如什么最长公共子序列,什么最长递增子序列,最多嵌套矩阵等等等等,里面都有一个“最”字,这类问题虽然有很多其他可行的解,但是我们需要一个最优解(这里的一个最优解不是唯一一个,而是符合条件的一个即可)。


动态规划的设计步骤:

  • 刻画一个最优解的结构特征
  • 递归地定义最优解的值(就是求递推式)
  • 计算出最优解的值,通常采用自底向上的方法
  • 利用计算出的信息构造出一个最优解

步骤1~3是动态规划算法求解问题的基础,而如果需要构造出一个最优解,就需要步骤4了。


动态规划实现方法:

即上一个步骤中的步骤3,通常采用自底向上的方法,其实还有自顶向下的方法。

  • 带备忘的自顶向下法:其实就是俗称的“记忆化递归”。此方法仍按照自然的递归形式编写过程,但过程会保存每个子问题的解。当需要一个子问题的解时,过程首先检查是否已经保存过此解,如果是,则直接返回保存的值,无需再求一次。

  • 自底向上法:这种方法需要恰当地定义子问题“规模”的概念,使得任何子问题的求解都只依赖于“更小的”子问题的求解。因而我们可以将子问题按规模排序,按由小至大的顺序进行求解。当求解某个子问题时,它所依赖的那些更小的子问题都已求解完毕,结果已经保存。每个子问题只需求解一次,当我们求解它时,它的所有前提子问题都以求解完成。

为什么经常采用“自底向上”的方法呢?
因为虽然两种方法的渐进运行时间相同,但是在某些特殊情况下,自顶向下方法并未真正递归地考察所有可能的子问题。


动态规划原理

最优子结构

在发掘最优子结构性质的过程中,实际上遵循了如下的通用模式:

  • 证明问题最优解的第一个组成部分是做出一个选择。
  • 对于一个给定问题,在其可能的第一步选择中,你假定已经知道那种选择才会得到最优解。
  • 给定可获得最优解的选择后,你确定这次选择会产生哪些子问题,以及如何最好地刻画子问题空间
  • 利用“剪切—粘贴”技术证明:作为构成原问题最优解的组成部分,每个子问题的解就是它本身的最优解。

对于不同问题领域,最优子结构的不同体现在两个方面:

  • 原问题的最优解中涉及多少个子问题
  • 在确定最优解使用哪些子问题时,我们需要考察多少种选择。

在动态规划方法中,我们通常自底向上地使用最优子结构。首先先求得子问题的最优解,然后再求原问题的最优解。在求解原问题过程中,我们需要在涉及的子问题中做出选择,选出能得到原问题最优解的子问题。原问题最优解的代价通常就是子问题最优解的代价再加上由此选择直接产生的代价。

0 0