動態規劃演算法(一)

2021-08-16 17:39:02 字數 3193 閱讀 5200

動態規劃與分治方法相似,均是通過子問題的解求解原問題。區別是分治演算法在求解子問題時會做許多不必要的工作,它會反覆求解那些公共子問題;而動態規劃演算法對每個子子問題都只求解一次,將其解儲存在乙個**中,從而無需每次求解子子問題時都重新計算,避免了不必要的計算工作。

鋼條切割問題:給定一段長度為n英吋的鋼條和乙個**表pi(i=1,2,...n),求切割鋼條方案,使得銷售收益rn最大。

長度i123

4567

8910**pi15

891017

1720

2430

先說一下整體的求解方法:將鋼條從左邊切割下長度為i的一段,只對右邊剩下的長度為n-i的一段繼續進行切割,對左邊的一段則不再進行切割。我們可以用公式來描述上述方法

rn=max(pi+rn-i)      1<=i<=n

首先用分治的思想求解最優鋼條切割問題

這是一種直接的自頂向下的遞迴方法,這種方法效率極低,因為cut-rod反覆地求解相同的子問題。通過圖例來說明此問題:

圖中,從父節點s到子節點t的邊表示從鋼條左端切下長度為s-t的一段,然後繼續遞迴求解剩餘的規模為t的子問題。可以看出,在圖中有許多相同的子樹,比如以1、2為根的子樹,在利用前面的演算法求解時,每次都要對相同的子問題多次求解,導致效率很低。

使用動態規劃方法求解最優鋼條切割問題

前面的演算法最大的問題就是反覆求解相同的子問題,而動態規劃方法通過安排求解順序,做到對每個子問題只求解一次,並將結果儲存下來。以後再次需要此子問題的解時,只需查詢儲存的結果(通過空間換取時間)。

帶備忘的自頂向下法

memoized-cut-rod(p,n)

for i=0 to n

r[i]=-1

return memoized-cut-aux(p,n,r)

memoized-cut-rod-aux(p,n,r)

if r[n]>=0

return r[n]

if n==0

q=0else q=-10000

for i=1 to n

q=max(q,p[i]+memoized-cut-rod-aux(p,n-i,r))

r[n]=q

return q

用c++實現如下:

int cut_rod_aux(vectorp, int n, vectorr) 

r[n] = q;

return q;

}int cur_rod(vectorp, int n)

int main()

; int max = cur_rod(v, 9);

cout << max << endl;

system("pause");

return 0;

}

帶備忘的遞迴演算法為每個子問題維護乙個表項來儲存它的解。每個表項的初值設為乙個特殊值,表示尚未填入子問題的解。當遞迴呼叫過程中第一次遇到子問題時,計算其解,並存入對應表項。隨後每次遇到同乙個子問題,只是簡單地查表,返回其解。

自底向上的動態規劃演算法

bottom-up-cut-rod(p,n)

r[0]=0

for j=1 to n //從小打大,

q=-1

for i=1 to j //i是切割點

q=max(q,p[i]+r[j-i]) //計算長度為j時的最大銷售收益

r[j]=q //儲存長度為j時的最大銷售收益

return r[n] //返回長度為n時的最大銷售收益

上述方法需要恰當定義子問題「規模」的概念,使得任何子問題的求解都只依賴於更小的子問題的求解。所以通過將子問題按規模排序,按從小到大的順序進行求解。當求解某個子問題時,它所依賴的那些更小的子問題都已經求解完畢,結果已經儲存。這樣,每個子問題只需求解一次,當求解乙個子問題時,它的所有前提子問題都已求解完成。

求解規模為j的子問題的方法與cut-rod所採用的方法相同,只是通過乙個陣列將r[j]的元素儲存下來,直接訪問r[j-i]來獲得規模為j-i的子問題的解,而不必進行遞迴呼叫。

擴充的動態規劃演算法(可以計算出切割後的鋼條的長度)

extended-bottom-up-cut-rod(p,n)

r[0]=0

for j=1 to n

q=-1

for i=1 to j

if q

print-cut-rod-solution(p,n)

(r,s)=extended-bottom-up-cut-rod

while n>0

print s[n]

n=n-s[n]

extended-bottom-up-cut-rod(p,n)演算法是在bottom-up-cut-rod上的略微改進,新建立陣列s,在求解規模為j的子問題時將第一段鋼條的最優切割長度i儲存在s[j]中。

print-cut-rod-solution(p,n)演算法通過呼叫

extended-bottom-up-cut-rod(p,n)來計算切割下來的每段鋼條的長度s[1...n],最後輸出長度為n的鋼條的完整的最優切割方案。

動態規劃演算法

一 動態規劃演算法原理 將待求解的問題分解成若干個相互聯絡的子問題,先求解子問題,然後從這些子問題的解得到原問題的解 對於重複出現的子問題,只在第一次遇到的時候對它進行求解,並把答案儲存起來。了不去求解相同的子問題,引入乙個陣列,把所有子問題的解存於該陣列中,這就是動態規劃所採用的基本方法。動態規劃...

動態規劃演算法

動態規劃 通過把原問題分解為相對簡單的子問題來求解複雜問題。動態規劃常常適用於有重疊子問題和最優子結構性質的問題。演算法總體思想 演算法的基本步驟 演算法的基本要素 最優子結構 重疊子問題 備忘錄方法 問題描述 子串行 公共子串行 最長公共子串行 lcs 問題 問題分析 動態規劃求解lcs問題 最長...

動態規劃演算法

動態規劃演算法的思路 動態規劃法即 dynamic programming method dp 是系統分析中的種常用方法。動態規劃法是20世紀50年代由貝爾曼 r.bellman 等人提出的,用來解決多階段決策過程問題的一種最優化方法。多階段決策過程是指把研究問題分成若干個相互聯絡的階段,由每個階段...