算法导论笔记——第十五章 动态规划

通常用来解决最优化问题。在做出每个选择的同时,通常会生成与原问题形式相同的子问题。当多于一个选择子集都生成相同的子问题时,动态规划技术通常就会非常有效。其关键技术就是对每个这样的子问题都保存其解,当其重复出现时即可避免重复求解。

  分治:划分为互不相交的子问题,递归求解子问题,再将他们的解组合起来。

  动态规划(dynamic programming,表格法而非编程)用于子问题重叠的情况。

四个步骤来设计一个动态规划算法:

  1 刻画一个最优解的结构特征

  2 递归地定义最优解的值

  3 计算最优解的值,通常采用自底向上的方法

  4 利用计算出来的信息构造一个最优解

最优子结构:问题的最优解由相关子问题的最优解组合而成,而这些子问题可以独立求解。

实现方法

带备忘的自顶向下法(top-down with memoization)

自底向上法(bottom-up method), 复杂度系数更小。

 

15.3 动态规划原理

适合应用动态规划方法求解的最优化问题应具备的两个要素:最优子结构子问题重叠

发掘最优子结构的通用模式:

做出一个选择。它会产生一个或多个待解的子问题。

在可能的第一步选择中,假定已经知道哪种选择会得到最优解

确定这次选择会产生哪些子问题,以及如何最好的刻画子问题空间

每个子问题的解就是它本身的最优解。

一个刻画子问题空间的好经验:保持子问题空间尽可能简单,只有必要时才扩展它。

对于不同问题领域,最优子结构的不同体现在两个方面:最优解用到的子问题总数和确定最优选择时需要考察多少种选择。

可用其乘积来粗略分析运行时间。

子问题必须无关(最长简单路径问题就不能使用动态规划)。如果求解一个子问题用到了某些资源,导致这些资源在求解其他子问题时不可用,则不能动态规划。

如果每个子问题都必须至少求解一次:自底向上

如果子问题空间的某些子问题完全不必求解:自顶向下(递归方式+备忘录)

 

15.4 最长公共子序列(LCS)

一个给定序列的子序列,就是将给定序列中零个或多个元素去掉之后得到的结果。即不要求连续,故不同于子串,但类似于模糊匹配中的*。

定理15.1(LCS的最优子结构) 令X=<x1,x2,...,xm>,Y=<y1,y2,...,yn>为两个序列,Z=<z1,z2,...,zk>为X和Y的任意LCS。

1. 如果xm=yn,则zk=xm=yn且Zk-1是Xm-1和Yn-1的一个LCS。

2. 如果xm!=yn,则zk!=xm意味着Z是Xm-1和Y的一个LCS。

3. 如果xm!=yn,则zk!=yn意味着Z是X和Yn-1的一个LCS。

可以用m*n的数组或者约max(m,n)+O(1)的空间来查找到LCS的长度。如需重构,为了保证O(m+n)的重构时间,则大约需要m*n空间。

 

15.5 最优二叉搜索树

形式化定义:给定一个n个不同关键字的已排序的序列K=<k1,k2,...,kn>(因此k1<k2<...<kn),我们希望用这些关键字构造一棵二叉树。对每个关键字ki,都有一个概率pi表示其搜索概率。n个关键字及n+1个不存在的伪关键字都带搜索概率。搜索代价最小的二叉搜索树,叫做最优二叉搜索树。

不一定是高度最矮的,概率最高的关键字也不一定出现在二叉搜索树的根结点。

步骤1:最优二叉搜索树的结构

  任意子树包含连续关键字ki,...,kj,叶节点di-1,...,dj(失败搜索)。

  最优子结构:如果一个最优二叉树T有一棵包含关键字ki,...,kj的子树T’,那么T’必然是包含关键字ki,...,kj和伪关键字di-1,...,dj的子问题的最优解。

步骤2:一个递归算法

  注意成为子树后高度增加1

步骤3:计算最优二叉搜索树的期望搜索代价

 

posted on 2017-08-17 18:23  胖子一刚  阅读(187)  评论(0编辑  收藏  举报

导航