《算法导论》第15章 动态规划 个人笔记

来源:互联网 发布:网贷系统源码下载 编辑:程序博客网 时间:2024/05/18 03:06

第15章 动态规划

15.1 钢条切割

1、递归实现:

CUT-ROD(p,n)if n == 0    return 0q = -\inffor i = 1 to n    q = max(q,p[i]+CUT-ROD(p,n-i))return q

分析CUT-ROD的运行时间,令T(n)表示第2个参数值为n时CUT-ROD的调用次数。

T(n)=1+j=0n1T(j)=2n

2、使用动态规划

  • 带备忘的自顶向上法
MEMOIZED-CUT-ROD(p,n)let r[0..n] be a new arrayfor i = 0 to n    r[i] = -\infreturn MEMOIZED-CUT-ROD-AUX(p,n,r)MEMOIZED-CUT-ROD-AUX(p,n,r)if r[n] >= 0    return r[n]if n == 0    q = 0else q = -\inf    for i = 1 to n        q = max(q,p[i]+MEMOIZED-CUT-ROD-AUX(p,n-i,r))r[n] = qreturn q
  • 自底向上法
BOTTOM-CUT-ROD(p,n)let r[0..n] be a new arrayr[0] = 0for j = 1 to n    q = -\inf    for i = 1 to j        q = max(q,p[i]+r[j-i])    r[j] = qreturn r[n]

两种方法具有相同的渐进运行时间,但自底向上法没有频繁的递归函数调用的开销,所以较自顶向下法有更小的系数。

3、重构解

EXTENDED-BOTTOM-CUT-ROD(p,n)let r[0..n] and s[0..n] be a new arrayr[0] = 0for j = 1 to n    q = -\inf    for i = 1 to j        if q < p[i]+r[j-i]            q = p[i]+r[j-i]            s[j] = i    r[j] = qreturn r[n]PRINT-CUT-ROD-SOLUTION(p,n)(r,s) = EXTENDED-BOTTOM-CUT-ROD(p,n)while n > 0    print s[n]    n = n - s[n]

15.2 矩阵链乘法

m[i,j]表示AiAi+1...Aj矩阵链的最优解

MATRIX-CHAIN-ORDER(p)n = p.length - 1let m[1..n,1..n] and s[1..n-1,2..n] be a new arrayfor i = 1 to n    m[i,i] = 0for l = 2 to n  //l is the chain length    for i = 1 to n-l+1        j = i + l -1        m[i,j] = \inf        for k = i to j-1            q = m[i,k] + m[k+1,j] + p[i-1]p[k]p[j]            if q < m[i,j]                m[i,j] = q                s[i,j] = kreturn m,sPRINT-OPTIMAL-PARENS(s,i,j)if i == j    print "A"else print "("    PRINT-OPTIMAL-PARENS(s,i,s[i,j])    PRINT-OPTIMAL-PARENS(s,s[i,j]+1,j)    print ")"

15.3 动态规划原理

最优子结构

在发掘最优子结构性质的过程中,实际上遵循了如下的通用模式:
1. 证明问题最优解的第一个组成部分是做出一个选择
2. 对于一个给定问题,在其可能的第一步选择中,假定已经知道哪种选择才会得到最优解
3. 给定可获得最优解的选择后,确定这次选择会产生哪些子问题,以及如何最好地刻画子问题空间
4. 利用“剪切-粘贴”技术证明作为构成原问题最优解的组成部分,每个子问题的解就是它本身的最优解

重叠子问题

适合用动态规划方法求解的最优化问题,其子问题空间必须足够“小”。如果递归算法反复求解相同的子问题,我们就称最优化问题具有重叠子问题。

重构最优解

维护记录每个子问题最优位置的表,重构时只需O(1)时间。

备忘

在低效的递归算法加入备忘机制可称为自顶向下动态规划法。通常情况下,自底向上动态规划算法没有递归调用的开销,会比自顶向下备忘算法快。但对于某些问题,它的子问题空间中的某些子问题完全不必求解,备忘方法就会体现出优势了,因为它只会求解那些绝对必要的子问题。

15.4 最长公共子序列

public static int lcs(String str1, String str2) {    int len1 = str1.length();    int len2 = str2.length();    int c[][] = new int[len1+1][len2+1];    for (int i = 1; i <= len1; i++) {        for( int j = 1; j <= len2; j++) {            if (str1.charAt(i-1) == str2.charAt(j-1))                c[i][j] = c[i-1][j-1] + 1;            else                c[i][j] = max(c[i - 1][j], c[i][j - 1]);        }    }    return c[len1][len2];}

15.5 最优二叉搜索树

OPTIMAL-BST(p,q,n)let e[1..n+1,0..n],w[1..n+1,0..n], and root[1..n,1..n] be new tablesfor i = 1 to n+1    e[i,i-1] = q[i-1]    w[i,i-1] = q[i-1]for l = 1 to n    for i = 1 to n-l+1        j = i+l-1        e[i,j] = \inf        w[i,j] = w[i,j-1]+p[j]+q[j]        for r = i to j-1            t = e[i,r-1]+e[r+1,j]+w[i,j]            if t<e[i,j]                e[i,j]=t                root[i,j]=rreturn e,root