漫談演算法 動態規劃 Dynamic Programming
Dynamic Programming一直以來是自己比較弱的一部分,希望可以在這一塊有所提升。
動態規劃,Dynamic Programming。這裡的programming沒有翻譯成程式設計,是因為,這裡的programming的意思是指一個tabular method。其實這也暗示了DP的本質,用一個table儲存子問題的中間結果。(後面會有例子具體介紹)
和分治演算法比較類似,但不同的是分治演算法把原問題劃歸為幾個相互獨立的子問題,從而一一解決,而動態規劃則是針對子問題有重疊的情況的一種解決方案。
目前design DP主要有兩個思路:
一個是利用recursive method
另一個思路是exhaust search,這個好像是我們老師發明的方法,這裡有篇Kirk的論文, How to design dynamic programming algorithms sans recursion 有興趣的大家可以仔細研究一下,我下面也會簡單舉例介紹一下這個方法。
下面的例子中多數程式碼都是虛擬碼,旨在illustrate idea。同時節省時間。程式碼中都省去了backtrack的過程,即只得到了optimal solution的值,省去了如何construct optimal solution的過程。這個一般用一個數組記錄一下就OK了。
轉載於:http://www.cnblogs.com/Gavin_Liu/archive/2011/04/13/2011214.html
先來個比較簡單的例子(其實後面的也不難O(∩_∩)O~)
例:Rod-cutting problem(切木頭問題。感覺翻譯過來怎麼就變了味呢?囧。。。)
Input:有一個長n米的木頭,和一個price table,table如下:
長度 i 1 2 3 4 5 6 。。。
價格 Pi 1 5 8 9 10 17。。。
意思很明顯,就是長度為1米的木頭可以買1元,長5米的可以賣10元,依次類推
Output:找一個cut的方法,使最後賺的錢最多。
很顯然,這個遞迴的主要思路是我切一刀之後,分成兩段,一段我按table的價錢賣了,另一段我當成一個新的子問題,繼續作為我的函式的新的引數,這樣不就遞迴了嗎?(__) 但是問題是這一刀怎麼切,沒錯,我們就來個找最大值,即max_{i =1 to n} Pi + Cut(n-i).
所以,遞迴函式應該是:
Cut(P, n){ //P 就是我的table,n是木頭長度
if n == 0
return 0;
q = -infinity
for i = 1 to n
q = max(q,P[i]+Cut(P,n-i))
return q;
}
然後,根據這個recursive寫DP
Cut(P, n){
for(int i = 1; i<=n; i++){
q = -infinity;
for(int j = 1; j<=i; j++)
q = max(q, P[j] + r[i-j]);
r[i] = q;
}
return r[n];
}