【算法復習】動態規划


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)

 

## 樹形動態規划

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM