zoukankan      html  css  js  c++  java
  • 【算法复习】动态规划

    Outline

    • 动态规划原理
    • 编号动态规划:最大不下降子序列
    • 划分动态规划:矩阵链乘、凸多边形三角剖分
    • 数轴动态规划:0-1背包
    • 前缀动态规划:最长公共子序列
    • 树形动态规划:最优二分搜索树

    Notes

    ## 动态规划原理

    • 基本思想:问题的最优解如果可以由子问题的最优解推导得到,则可以先求解子问题的最优解,在构造原问题的最优解;若子问题有较多的重复出现,则可以自底向上从最终子问题向原问题逐步求解。
    • 使用条件:可分为多个相关子问题,子问题的解被重复使用
      • Optimal substructure(优化子结构):
        • 一个问题的优化解包含了子问题的优化解
        • 缩小子问题集合,只需那些优化问题中包含的子问题,降低实现复杂性
        • 我们可以自下而上的
      • Subteties(重叠子问题):在问题的求解过程中,很多子问题的解将被多次使用。
    • 动态规划算法的设计步骤:
      • 分析优化解的结构
      • 递归地定义最优解的代价
      • 自底向上地计算优化解的代价保存之,并获取构造最优解的信息
      • 根据构造最优解的信息构造优化解
    • 动态规划特点:
      • 把原始问题划分成一系列子问题;
      • 求解每个子问题仅一次,并将其结果保存在一个表中,以后用到时直接存取,不重复计算,节省计算时间
      • 自底向上地计算。
      • 整体问题最优解取决于子问题的最优解(状态转移方程)(将子问题称为状态,最终状态的求解归结为其他状态的求解)

    ## 编号动态规划:最大不下降子序列

      本类的状态是基础的基础,大部分的动态规划都要用到它,成为一个维。

    • 最长不下降子序列定义:从序列中选出若干个数组成一个新的序列,不改变他们的队伍的顺序,要求新的序列里xi≤xi+1≤xi+1.....举个例子{4,6,5,7,3},最长不下降子序列就是{4,6,7}。

    • 子问题的表示:令dp[i]表示以第i个元素结尾的前i个元素构成的最长不下降子序列的长度
    • 优化子结构:若最长不下降子序列包括ak,则必有一个解包含a1,a2…ak-1的最长不下降子序列,dp[i]表示为前i个元素的序列的最长不下降子序列
    • 方程 dp[i] = max{dp[j] | 0<j<i , aj≥ai} + 1
    • 伪代码

        输入a[1,...,n]  输出:最长子序列

          

    时间复杂度:O(n^2)

     ## 划分动态规划

    【矩阵链乘】

    • 优化子结构:若计算A1~n的优化顺序在k处断开矩阵链, 即A1~n=A1~k × Ak+1~n,则在A1~n的优化顺序中,对应于子问题A1~k的解必须是A1-k的优化解,对应于子问题Ak+1~n的解必须是Ak+1~n的优化解
    • 子问题重叠性:

        

    • 方程:

    假设:m[i, j] = 计算Ai~j的最小乘法数;    A1 ... AkAk+1 .... An 是优化解(k实际上是不可预知)

       

         

    • 伪代码:
    输入:<A1, A2, ..., An>, Ai是矩阵
    输出:计算A1 x A2 x ... x An的最小代价方法
    
    Matrix-Chain-Order(p)
    n=length(p)-1;
    FOR i=1 TO n DO
        m[i, i]=0;
    FOR l=2 TO n DO /* 计算地l对角线*/
        FOR i=1 TO n-l+1 DO
            j=i+l-1;
            m[i, j]= ∞;
            FOR k←i To j←1 DO /* 计算m[i,j] */
                 q=m[i, k]+m[k+1, j]+ pi-1pkpj
                 IF q<m[i, j] THEN 
    m[i,j]=q; s[i,j]=k; Return m and s.
    Print-Optimal-Parens(s, i, j) //构建最优解,输出A1-n的优化计算顺序
     IF j=i
     THEN Print “A”i;
     ELSE Print “(”
         Print-Optimal-Parens(s, i, s[i, j])
         Print-Optimal-Parens(s, s[i, j]+1, j)
         Print “)”
    • 算法复杂度
      • 计算代价的时间:三层循环 O(n3)
      • 构建最优解的时间: O(n)
      • 总时间复杂度:O(n3)
    •  空间复杂度
      • 使用数组m和s
      • 需要空间O(n3)

     【三角剖分】

    • 优化子结构:将多边形P划分为不相交三角形的弦的集合
    • 优化问题:

    • 方程:设t[i,j] = <vi-1,vi,.....,vj>的优化三角剖分代价

       

    ## 数轴动态规划:0-1背包

    • 问题描述:给定n种物品和一个背包,物品i的重量是wi,价值vi,背包容量为C,问如何选择装入背包的物品,使装入背包中的物品的总价值最大?对于每种物品总能选择完全装入或不装入,一个物品最多装入一次。
    • 等价整数规划问题:

        

    • Naive的方法:每个物品只有两种选择:不装或装,n个物品共2n个装取方案,每个装取方案的计算代价为n,总计算代价为O(n2n)
    • 问题的划分:

       

    • 定义代价矩阵m与方程:   
      • 定义m(i, j) :背包容量为j,可选物品为xi,xi+1…xn时,问题的最优解代价时m[i,j]
      • m(n, j) = 0,   0 ≤ j <wn
      • m(n, j) = vn,   j ≥wn
      • m(i, j) =  m(i+1, j),         0≤ j< wi
      • m(i, j) =  max{m(i+1, j), m(i+1, j-wi)+vi},      j ≥ wi
    • 优化子结构和自底向上的代价

      

    • 伪代码

    输入:C>0, wi>0, vi>0, 1≤ i≤n
    输出:(x1, x2, …, xn), xi∈{0, 1}, 满足 ∑1≤i≤nwi xi ≤C, ∑1≤i≤nvi xi 最大


    For j=0 To min(wn-1, C) Do m[n, j] = 0; For j=wn To C Do m[n, j] = vn; For i=n-1 To 2 Do For j=0 To min(wi -1, C) Do m[i, j] = m[i+1, j]; For j=wi To C Do m[i, j]=max{m[i+1, j], m[i+1, j-wi]+vi}; If C<w1 Then m[1, C]=m[2, C]; Else m[1, C]=max{m[2, C], m[2, C-w1]+v1};
    m(1, C)是最优解代价值,相应解计算如下: //构造优化解
        If m(1, C) = m(2, C)
        Then x1 = 0;
        Else x1 = 1;
    如果x1=0, 由m(2, C)继续构造最优解;
    如果x1=1, 由m(2, C-w1)继续构造最优解.
    • 时间复杂度:
      • 计算代价的时间为O(Cn)
      • 构造最优解的时间:O(Cn)
      • 总时间复杂度为:O(Cn)
    • 空间复杂度:
      • 使用数组m,需要空间O(Cn)

    ## 前缀动态规划:最长公共子序列(LCS)

    •  问题描述:Z是序列X与Y的公共子序列如果Z是X的子序列也是Y的子序列。
    •  Naive方法:
      • 枚举X的每个子序列Z
      • 检查Z是否为Y的子序列
      • T(n)=O(n2m)
    •  优化子结构:
      • 设X=(x1, ..., xm)、Y=(y1, ..., yn)是两个序列, LCSXY=(z1, ..., zk)是X与Y的LCS,我们有:
      •  如果xm=yn, 则zk=xm=yn, LCSXY = LCSXm-1Yn-1 + <xm=yn>,   LCSXm-1Yn-1是Xm-1和Yn-1的LCS.
      •  如果xm≠yn,且zk≠xm,则LCSXY是Xm-1和Y的LCS,即 LCSXY = LCSXm-1Y
      •  如果xm≠yn,且zk≠yn,则LCSXY是X与Yn-1的LCS,即 LCSXY = LCSXYn-1

        

    • 子问题重叠性

    • 方程:

        

    •  自底向上计算

        

    • 伪代码

    输入:X = (x1,x2,...,xm),Y = (y1,y2,...yn)
    输出:Z = X与Y的最长公共子序列
    
    C[0:m,0:n]: C[i,j]是Xi与Yj的LCS的长度   B[1:m,1:n]:
    B[i,j]是指针,指向计算C[i,j]时所选择的子问题的优化解所对应的C表的表项
    
    LCS-length(X, Y)
    m←length(X);n←length(Y);
    For i←0 To m Do C[i,0]←0;
    For j←0 To n Do C[0,j]←0;
    For i←1 To m Do
      For j←1 To n Do
        If xi = yj
        Then C[i,j]←C[i-1,j-1]+1;B[i,j]←“↖”;
          Else If C[i-1,j]≥C[i,j-1] Then
                  C[i,j]←C[i-1,j]; B[i,j]←“↑”;
               Else C[i,j]←C[i,j-1]; B[i,j]←“←”;
    Return C and B.
    
    Print-LCS(B, X, i, j)
    IF i=0 or j=0 THEN Return;
    IF B[i, j]=“↖”
    THEN Print-LCS(B, X, i-1, j-1);
        Print xi;
    ELSE If B[i, j]=“↑”
        THEN Print-LCS(B, X, i-1, j);
        ELSE Print-LCS(B, X, i, j-1).
    
    Print-LCS(B, X, length(X), length(Y))
          可打印出X与Y的LCS。
    • 时间复杂度
      • 计算代价的时间:O(mn)
      • 构造最优解的时间:O(m+n)
      • 总时间复杂度为: O(mn)
    • 空间复杂度
      • 使用数组C和B,需要空间O(mn)

    ## 树形动态规划

     

  • 相关阅读:
    树型表的设计 上海
    FTP通讯封装 上海
    线程淡写 上海
    TCP通讯故障 上海
    设计模式引导 上海
    初试Delegate 上海
    c# 扫描端口 上海
    攻读计算机研究生的看法(转载) 上海
    挖掘表字段中的汉字 上海
    新生活运动 上海
  • 原文地址:https://www.cnblogs.com/hithongming/p/9229871.html
Copyright © 2011-2022 走看看