動態規劃與分治法相似,都是通過組合子問題的解來求解原問題。回顧下分治法的原理:它將問題劃分為互不相交的子問題(注意:互不相交),遞迴求解子問題,再將它們的解組合起來,即為原問題的解。
但是,動態規劃與分治法不同,有以下幾點:
1)對於子問題重疊的情況,分治法則重複求解,不高效。而動態規劃對每個子問題只求解一次,因為它將子問題的解進行儲存,當遇到重複的子問題時,不再計算,只需查詢替代即可;
2)動態規劃對原問題的劃分存在n種子問題劃分的可能性,它需要從n種劃分中選擇最優解,故動態規劃常被用於求解最優化問題;
接下來,通過鋼條切割的案例展示動態規劃的運用。
鋼條切割問題的描述:給定一段長度為n英吋的鋼條和乙個**表,求鋼條切割的方案,使得銷售收益最大化。
鋼條的長度和**
length : 1 2 3 4 5 6 7 8 9 10
price : 1 5 8 9 10 17 17 20 24 30
問題的分解方式:將長度為n的鋼條切割分解為左邊開始一段i,以及對右邊剩餘長度為n-i的鋼條繼續切割(遞迴求解),對左邊的一段不再進行切割。於是,最大切割收益可以描述為:
接下來通過n=4的鋼條切割問題的子問題圖來說明重疊子問題。
上圖,n=4時的鋼條切割子問題圖。頂點的標號給出了子問題的規模。有向邊(x,y)表示求解x時需要子問題y的解。舉例:n=4時,它包含子問題n=3,2,1,0;n=3時,它包含子問題n=2,1,0。所以重疊的子問題即為n=2,1,0,故當求解了n=3的子問題,對於n=4時的其他子問題,如n=2,1,0不需要再次求解,只需要查詢替代即可。
先來看自頂向下實現的切割。
memoized_cut_rod(p,n)
let r[0..n] be a new array
for i=0 to n
r[i]=-1
return memorized_cut_rod_aux(p,n,r);
memorized_cut_rod_aux(p,n,r)
if r[n]>=0
return r[n]
if n==0
q=0else
q=-1
for i=1 to n
q=max(q,p[i]+memorized_cut_rod_aux(p,n-i,r))
r[n]=q
return q
本文對自頂向下的切割用c進行實現,但是這裡提及切割的另乙個版本自底向上,下面是其偽**。
對n=4,本演算法給出的收益是10,符合要求。對於其他長度,可自行驗證。
動態規劃 鋼條切割問題
已知鋼條切割的不同長度對應的不同 如下所示 長度i 1 23 45 67 89 10 pi 1589101717202430 求輸入長度,輸出最佳的收益。詳細理論知識見 演算法導論第十五章 p359 書中給出三個演算法 一 自頂向下遞迴實現 缺點 當n足夠大時,時間會 性地增長。偽 cut rod ...
動態規劃 鋼條切割問題
一家公司購買長鋼條,將其切割成短鋼條 切割本身沒有成本,長度為i的短鋼條的 為pi。那給定一段長度為n的鋼條和乙個 表pi,求鋼條的切割方案使得收益rn最大。如乙個pi如下 長度i123 4567 8910 pi15 891017 1720 2430 在距離鋼條左端i長度處,我們總是可以選擇切割或者...
動態規劃 鋼條切割問題
動態規劃主要用於求解最優化問題,方法與分治法類似,也是將原問題分解成多個子問題,通過遞迴的方法求解子問題。不同之處就是動態規劃會通過增加程式空間複雜度的方式來將時間複雜度為指數級降低為多項式,通俗的講就是動態規劃會利用陣列記錄下子問題的結果,當再需要計算該子問題時直接呼叫該結果即可,就不用再去計算,...