最近在leetcode和牛客網上刷題,經常碰到一些和動態規劃相關的問題,雖然動態規劃的思路貌似不難,但是在具體的應用場景上卻總是困擾我,很難巧妙結合,決定寫一篇部落格來記錄下我對動態規劃的理解和遇到的各種問題以及如果將理論與實際編碼結合。
這篇部落格不是一次寫成的,我會陸續將我遇到的、我認為有代表性的動態規劃問題和解法在此進行總結。
動態規劃(dynamic programming,簡稱dp)通過把原問題分解為相對簡單的子問題進行求解。動態規劃的思想很簡單,就是把原問題分解為一系列子問題,然後由這些子問題逐漸組成更複雜的原問題。通常,子問題之間十分相似,動態規劃試圖僅解決每個子問題一次,從而減少計算量。一旦某個子問題已經解出,就將其記憶化儲存,下次再遇到相同問題時可以查表。這種做法在重複子問題的數目關於輸入的規模呈指數增長時特別有用。(以上參考維基百科定義)
其實對於我來說,第一次接觸動態規劃是在大學時的資料結構課堂上,當時老師在求解fobinacci數列採用遞迴演算法,這種遞迴演算法存在大量重複的子問題。比如求f(10),因為f(10)=f(9)+f(8),而f(9)=f(8)+f(7),可以看到,這裡需要兩次求f(8),繼續向下擴充套件,複雜度呈指數增加。把這些遞迴演算法用迭代替換問題就可以得到解決,老師當時說這種用迭代替換遞迴的思路就叫動態規劃,這個印象也在我腦海裡很多年。
動態規劃其實適用於解決這樣的問題,這類問題需要包含三類性質:
重疊子問題。它將問題重新組合成子問題。為了避免多次解決這些子問題,它們的結果都逐漸被計算並被儲存,從簡單的問題直到整個問題都被解決。因此,動態規劃儲存遞迴時的結果,因而不會在解決同樣的問題時花費時間。
無後效性。即子問題的解一旦確定,就不再改變,不受在這之後、包含它的更大的問題的求解決策影響。
子問題重疊。子問題重疊性質是指在用遞迴演算法自頂向下對問題進行求解時,每次產生的子問題並不總是新問題,有些子問題會被重複計算多次。動態規劃演算法正是利用了這種子問題的重疊性質,對每乙個子問題只計算一次,然後將其計算結果儲存在乙個**中,當再次需要計算已經計算過的子問題時,只是在**中簡單地檢視一下結果,從而獲得較高的效率。
接下來我們參照兩個實際例子來理解。
最簡單的計算演算法,就是遞迴了,如下所示。
int func(int n)
當n=5時,計算過程如下:
fib(5)
fib(4) + fib(3)
(fib(3) + fib(2)) + (fib(2) + fib(1))
((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
(((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
由上面可以看到,這種演算法計算了大量的重複的子問題,因此效率不高,事實上它的運算時間是指數增長的。改進的方法可以是將中間結果存起來,也就是所謂的將遞迴變成迭代,**如下所示。
int func(int n)。
這裡需要解釋一下狀態轉移方程,其實對於前i個物品放入容量為v的揹包來說,相較於前i-1個物品放入容量為v的揹包來說,最大的差別就是第i個物品是不是放入揹包,如果不放入揹包,那麼f[i][v]=f[i-1][v],如果第i個元素放入揹包,那麼f[i][v]=f[i-1][v-c[i]]+w[i],至於究竟放入還是不放入,就要看它們兩個誰比較大了。接下來我們給你乙個示例**。
int func(vectorvalue,vectorweight,int w)}}
return res[value.size()][w];
}
當然有很多種簡化的編碼方法,這裡為了敘述一般意義下的做法,先初始化然後逐步將子問題向目標推進。 動態規劃演算法
一 動態規劃演算法原理 將待求解的問題分解成若干個相互聯絡的子問題,先求解子問題,然後從這些子問題的解得到原問題的解 對於重複出現的子問題,只在第一次遇到的時候對它進行求解,並把答案儲存起來。了不去求解相同的子問題,引入乙個陣列,把所有子問題的解存於該陣列中,這就是動態規劃所採用的基本方法。動態規劃...
動態規劃演算法
動態規劃 通過把原問題分解為相對簡單的子問題來求解複雜問題。動態規劃常常適用於有重疊子問題和最優子結構性質的問題。演算法總體思想 演算法的基本步驟 演算法的基本要素 最優子結構 重疊子問題 備忘錄方法 問題描述 子串行 公共子串行 最長公共子串行 lcs 問題 問題分析 動態規劃求解lcs問題 最長...
動態規劃演算法
動態規劃演算法的思路 動態規劃法即 dynamic programming method dp 是系統分析中的種常用方法。動態規劃法是20世紀50年代由貝爾曼 r.bellman 等人提出的,用來解決多階段決策過程問題的一種最優化方法。多階段決策過程是指把研究問題分成若干個相互聯絡的階段,由每個階段...