【算法複習】動態規劃

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)spa

 

 ## 劃分動態規劃

【矩陣鏈乘】設計

  • 優化子結構:若計算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)

 【三角剖分】code

  • 優化子結構:將多邊形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 最大blog


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)

 

## 樹形動態規劃

相關文章
相關標籤/搜索