動態規划


   本文參考《算法導論》,整理者:華科小濤@http://www.cnblogs.com/hust-ghtao/眨眼

動態規划方法通常用來求解最優化問題。

1. 基本原理

    什么問題應該用動態規划方法來求解呢?

  1.    適合應用動態規划方法求解的最優化問題應該具備兩個要素:最優子結構重疊子問題
  2. 1.1 最優子結構

  3.    如果一個問題的最優解包含其子問題的最優解,我們就稱此問題具有最優子結構性質。使用動態規划算法時,我們用子問題的最優解來構造原問題的最優解。在動態規划方法中,我們通常自底向上的使用最優子結構。也就是說,首先求得子問題的最優解,然后求原問題的最優解。原問題最優解的代價通常是子問題最優解的代價再加上由此次選擇產生的代價。

  4. 1.2 重疊子問題

  5.    適用動態規划方法求解的最優化問題應該具備的第二個性質是子問題空間必須足夠小,即問題的遞歸算法會反復求解相同的子問題,而不是一直生成新的子問題。如果遞歸算法反復求解相同的子問題,我們就稱最優化問題具有重疊子問題性質。動態規划算法通常這樣利用重疊子問題性質:對每個子問題求解一次,將解存入一個表中,當再次需要這個子問題時直接查表,每次查表的代價為常亮時間。

  6. 1.3 基本步驟

 

    我們通常按照如下4個步驟來設計一個動態規划算法:

  • 刻畫一個最優解的結構特征。
  • 遞歸地定義最優解得結構特征。
  • 計算最優解的值,通常采用自底向上的方法。
  • 利用計算出的信息構造一個最優解。

2.鋼條切割問題

    題目是這樣的:給定一段長度為n英寸的鋼條和一個價格表pi(i=1,2,3…n),求鋼條切割方案,使得收益CodeCogsEqn最大。注意,如果長度為n英寸的鋼條價格CodeCogsEqn(1)足夠大,最優解可能就是完全不需要切割。下圖是一個價格表的樣例:

image

我們將鋼條從左邊切割下長度為i的一段,只對右邊剩下的長度為n-i的一段繼續切割,對左邊的一段不再進行切割。即問題的分解方式為:將長度為n的鋼條分解為左邊開始一段及剩余部分繼續分解的結果。不做任何切割的方案:第一段為n,收益為CodeCogsEqn(1),剩余部分長度為0,收益CodeCogsEqn(2)。於是得到最優解的結構特征:

                 image

2.1使用朴素遞歸算法

下面的過程實現了上述公式的計算,采用的是一種自頂向下的遞歸方法:

           image

我們發現,如果直接將此偽代碼用程序實現,一旦輸入規模稍微變大,運行時間將急劇增長。原因在於CUT-ROD反復的用相同的參數值對自身進行遞歸調用,即它反復求解相同的子問題。下圖顯示n=4的情況:

               image

為了分析CUT-ROD的運行時間,令CodeCogsEqn(3)表示第二個參數值為n時CUT-ROD的調用次數。此值等於遞歸調用樹中根為n的子樹中的節點總數,注意此值包含了根結點對應的最初的一次調用。因此CodeCogsEqn(4),並且

                                 CodeCogsEqn(5)

可證明CodeCogsEqn(6)

 

2.2 使用動態規划方法

    朴素遞歸算法之所以效率很低,是因為它反復求解相同的子問題。因此動態規划方法仔細安排求解順序,對每個子問題只求解一次。

    動態規划方法仔細安排求解順序,對每個子問題只求解一次,並將結果保存下來。如果隨后再次需要此子問題的解,只需查找保存的結果,而不必重新計算。

  • 帶備忘的自頂向下的方法

    此方法仍按自然的遞歸形式編寫過程,但過程中會保存每一個子問題的解。當需要一個子問題的解時,過程首先檢查是否已經保存過此解。如果是,則直接返回保存的結果,從而節省了計算時間;否則按通常方式計算這個子問題。

下面是偽代碼:

image

image

 

  • 自底向上的版本

    我們可以將子問題按規模從小到大進行排序,因為通常子問題只依賴於更小的子問題的求解,所以我們可以按規模由小到大的順序依次求解。當求解某個子問題時,它所依賴的更小的子問題都已經被求解保存,所以每個子問題只需求解依次,大大提高效率。

下面是自底向上版本的代碼:

image

 

通過分析可知,上述兩種方法的時間復雜度為CodeCogsEqn(7)

  • 重構解

前面鋼條切割問題的動態規划算法返回最優解的收益值,但是並未返回解本身。下面是擴展動態規划算法,不僅保存最優收益值,還保存最優的切割方案。BOTTOM-UP-CUT-ROD的擴展版本,它對長度為j的鋼條,不僅計算最大收益值CodeCogsEqn(8),還保存最優解對應的第一段鋼條的切割長度CodeCogsEqn(9)

image

image

下面的過程接受兩個參數:價格表CodeCogsEqn(10)和鋼條長度n,然后調用上面函數計算切割下來的每段鋼條長度,最后輸出長度為n的鋼條的完整的切割方案:

image

 

3.總結

    當問題具有最優子結構和重疊子問題時,可以考慮用動態規划算法。動態規划方法安排求解順序,對每個子問題只求解一次,並將結果保存下來。如果隨后再次需要此子問題的解,只需查找保存的結果,而不必重新計算。因此動態規划算法是付出額外的內存空間來節省計算時間,是典型的時空權衡的例子。


免責聲明!

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



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