動態規劃詳解

來源:互聯網
上載者:User

1                                                            1,1

3            2                                         2,1                    2,2

4           10           1                        3,1                  3,2                    3,3

4              3            2             20         4,1          4,2                     4,3                 4,4

(a)數字三角形                                                                 (b)狀態編號

 

從第一行的數開始,每一次可以向下或者向右走一格,一直走到最下行,把沿途的數全部加起來,如何使這個和最大?

如果熟悉回溯法,會發現這是一個動態決策問題,每次有兩種選擇,左下或者右下.用回溯法求出所有可能的路線,就可以從中選擇最優路線,但是有路線2的n次方條,效率不可忍受

可以用抽象的方法來思考問題,把當前位置看成一個狀態,用(i,j)位置來表示.然後定義狀態(i,j)的指標函數,d(i,j)為從格子(i,j)出發出發能獲得的最大值

看不同的狀態如何轉移,往左走,則走到(i+1,j),往右走,則走(i+1,j+1),自由選擇,選擇其中較大的一個

狀態轉移方程                d(i,j)=a(i,j)+max{d(i+1,j),d(i+1,j+1)}

如果從(i+1,j)出發得到部分和是最大的,則加上a(i,j)之後也是最大的 .這個性質叫做最優子結構

動態規劃的核心是狀態和狀態轉移方程.

實現計算

1.遞迴計算

int d(int i,int j){     return a[i][j]+(i==n? 0:d(i+1,j)>d(i+1,j+1));}

效率太低,遞迴時調用關係樹造成了重複計算

2.遞推計算

int i,j;for(j=1;j<=n;j++)     d[n][j]=a[n][j];for(i=n-1;i>=1;i—)   for(j=1;j<=i;j++)      d[i][j]=a[i][j]+d[i+1][j]>?d[i+1][j+1];

遞推的時間複雜度為   狀態總數x每個狀態的決策個數x決策時間

3.記憶化搜尋

int d(int i,int j){      if(d[i][j]>=0)        return d[i][j];      return d[i][j]=a[i][j]+(i==n?0:d(i+1,j)>?d(i+1,j+1));}


把計算結果儲存在d[i][j]中,每次記錄是否計算過

也可以用另一個數組vis[]儲存是否被計算過

0-1背包問題

n種物品,每種有無窮多個,第i種體積為vi,重量是wi,選一些到容量為c的背包中,使得背包內物體在總體積不超過c的前提下重量盡量大

剛才的方法已經不適用了,原來的狀態轉移太混亂了.要消除這種混亂,要讓決策有序化.這就是多段決策問題

每次做一次決策就可以得到解的一部分.所有的決策做完就得到最終解.回溯法中每個決策對應一顆子樹,每個解答書對應一個解.節點層數是下一個待填充位置cur,就是即將完成的決策序號,在動規中稱為階段

多段決策可用動態規劃解決.d(i,j)表示第i層,背包剩餘容量為j的最大重量和.

d(i,j)=max{d(i+1,j),d(i+1,j-V[i])+w[i]}

邊界是i>n時d(i,j)=0,j<0時為負無窮

白話一點,d(i,j)表示把第i,i+1,i+2,,,n個物品裝到容量為j的背包中的最大重量和,事實上,這個說法常用階段和層這樣的術語,

代碼(結果是d[1][c])

for(int i=n;i>=1;i—)    for(int j=0;j<=c;j++)    {           d[i][j]=(i==n? 0:d[i+1][j]);           if(j>=v[i])               d[i][j]>?=d[i+1][j-v[i]]+w[i];    }

i必須逆序枚舉,但j的迴圈次序是無關緊要的

還有一種對稱的狀態定義,用f(i,j)表示把前i個物品裝到容量為j的背包中的最大重量和

狀態轉移方程:  f(i,j)=max{f(i-1,j),f(i-1,j-v[i])+w[i]}

最終答案為g(n,C)

for(int i=1;i<=n;i++)    for(int j=0;j<=C;j++)    {          f[i][j]=(i==1? 0:f[i-1][j]);         if(j>=v[i])             f[i][j]>?=f[i-1][j-v[i]]+w[i];    }

動態規劃的類型很多,今天就介紹最優子結構和多段決策,還有樹形動規,集合動規,DAG動規日後為一一研究介紹

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.