1. 程式人生 > >演算法設計與分析(二)之動態規劃

演算法設計與分析(二)之動態規劃

第一篇:

動態規劃(Dynamic Programming)

  • 求解過程是多階段決策過程,每步處理一個字問題,可用於求解組合優化問題

  • 適用條件:問題要滿足優化原則或最優子結構性質,即:一個最優決策序列的任何子序列本身一定是相對於子序列的初始和結束狀態的最優決策序列

例項:最短路徑問題

問題: 
輸入: 
起點集合{S1,S2,…,Sn} 
終點集合{T1,T2,…,Tn} 
中間結點集, 
邊集E,對於任意邊e有長度 
輸出:一條從起點到終點的最短路徑

例項: 

演算法設計: 
蠻力演算法: 考察每一條從某個起點到某個終點的路徑,計算長度,從其中找出最短路徑。 
上述例項中,如果網路層數為k,那麼路徑條數將接近2的k次方。

動態規劃演算法:

 多階段決策過程。 
每步求解的問題是後面階段求解問題的子問題。每步決策將依賴於以前步驟的決策結果。

動態規劃求解: 

優化原則:最優子結構性質

  • 優化函式的特點:任何最短路的子路徑相對於子問題始、終點最短 

  • 優化原則:一個最優決策序列的任何子序列本身一定是相對於子序列的初始和結束狀態的最優決策序列

動態規劃演算法設計

動態規劃設計要素

  • 問題建模,優化的目標函式是什麼?約束條件是什麼?

  • 如何劃分子問題(邊界)?

  • 問題的優化函式值與子問題的優化函式值存在著什麼依賴關係?(遞推方程)

  • 是否滿足優化原則

  • 最小子問題怎樣界定?其優化函式值,即初始值等於什麼?

動態規劃演算法設計要素小結

  • 多階段決策過程,每步處理一個字問題,界定子問題的邊界

  • 列出優化函式的遞推過程及初值

  • 問題要滿足優化原則或最優子結構性質,即:一個最優決策序列的任何子序列本身一定是相對於子序列的初始和結束狀態的最優決策序列

動態規劃演算法的遞迴實現

小結

  • 與蠻力演算法相比較,動態規劃演算法利用了子問題優化函式間的依賴關係,時間複雜度有所降低

  • 動態規劃演算法的遞迴實現效率不高,原因在於同一子問題多次重複出現,每次出現都需要重新計算一遍。

  • 採用空間換時間策略,記錄每個子問題首次計算結果,後面再用時就直接取值,每個字問題只算一次。

動態規劃演算法的迭代實現

迭代計算的關鍵

  • 每個子問題只計算一次

  • 迭代過程

    • 從最小的子問題算起

    • 考慮計算順序,以保證後面用的值前面已經計算好

    • 儲存結構儲存計算結果–備忘錄

  • 解的追蹤

    遞迴和迭代這兩種實現的比較

    遞迴實現:時間複雜性高,空間較小 
    迭代實現:時間複雜性低,空間消耗多

    • 設計標記函式標記每步的決策

    • 考慮根據標記函式追蹤解的演算法

原因:遞迴實現子問題多次重複計算,子問題計算次數呈指數增長,迭代實現每個子問題只計算一次。

動態規劃時間複雜度: 
備忘錄各項計算量之和+追蹤解工作量 
通常追蹤工作量不超過計算工作量,是問題規模的多項式函式

動態規劃演算法的要素

  • 劃分子問題,確定子問題邊界,將問題求解轉變成多步判斷的過程。

  • 定義優化函式,以該函式極大(或極小)值作為依據,確定是否滿足優化原則

  • 列優化函式的遞推方程和邊界條件

  • 自底向上計算,設計備忘錄(表格)

  • 考慮是否需要設立標記函式

總結:動態規劃演算法設計要點

  1. 引入引數來界定子問題的邊界。注意子問題的重疊程度(動態規劃之所以比蠻力演算法好,效率高,是在於它的每一個子問題子算一次,如果動態規劃演算法裡面,它的子問題出現次數非常少,前面存放著,後面幾乎不再引用,這時相當於跟蠻力演算法就沒有太大區別了。所以只有字問題唄多次重疊出現,後面計算的時候多次要呼叫這個值,這個時候動態規劃演算法才能體現出它的時間效率)。

  2. 給出帶邊界引數的優化幻術定義與優化函式的遞推關係,找到遞推關係的初值。

  3. 判斷該優化問題是否滿足優化原則。

  4. 考慮是否需要標記函式。

  5. 採用自底向上的實現技術,從最小的子問題開始迭代計算,計算中用備忘錄保留優化函式和標記函式的值。

  6. 動態規劃演算法的時間複雜度是對所有字問題(備忘錄)的計算工作量求和(可能需要追蹤解的工作量)

  7. 動態規劃一般使用較多的儲存空間,這往往成為限制動態規劃演算法使用的瓶頸因素。(空間換時間)

更多關於hadoop,spark和機器學習,資料結構與演算法文章請關注本文公眾號: