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)

    ## 树形动态规划

     

  • 相关阅读:
    io学习
    asp.net文件上传进度条研究
    asp.net页面中的Console.WriteLine结果如何查看
    谨慎跟随初始目的不被关联问题带偏
    android 按钮特效 波纹 Android button effects ripple
    安卓工作室 日志设置
    安卓工作室 文件浏览器 android studio File browser
    一个新的Android Studio 2.3.3可以在稳定的频道中使用。A new Android Studio 2.3.3 is available in the stable channel.
    新巴巴运动网上商城 项目 快速搭建 教程 The new babar sports online mall project quickly builds a tutorial
    码云,git使用 教程-便签
  • 原文地址:https://www.cnblogs.com/hithongming/p/9229871.html
Copyright © 2011-2022 走看看