演算法之動態規劃-Rod cutting
阿新 • • 發佈:2019-01-05
問題描述:
給定長度為n的木頭,把它切分成小段賣,不同長度的木頭價格不一樣,求最優切法。如圖1:
可以劃分為如下情況
分為一份: 4 (max price:10)
分為兩份 : 1 3 or 2 2 or 3 1 (max price:10)
分為三份 : 1 1 2 or 1 2 1 or 2 1 1 (max price:7)
分為四分 : 1 1 1 1 (max price:4)
最終結果為這四種情況分割的最大售價: 10
動態規劃
找出子問題
定義:
i :長度為i的鋼管r[i] :為劃分長度為i的鋼管的最大售價和p[i] : 長度為i的鋼管的價格
假設存在
反證,如果不存在,肯定存在另一個值,使得長度為i的木棒產生最優切割:與假設矛盾。
最終表示式:
遞迴求解子問題
遞迴求解
cutRod(p, n){
if n ==0
return 0
q = [email protected] // 初始化為負無窮
for i = 1 to n
q = max(p[i] + cutRod(p, n -i))
return q
}
動態規劃
遞迴求解的缺點是從復計算大量相同問題,動態規劃的思路是把相同的問題記錄下來,之後直接查表得到相同問題的解,避免重複計算,用空間換取時間,並且效果明顯。
upBottomCutRod(p, n) {
let r[0...n] be a new array
for i = 0 to n
r[i] = [email protected] // 初始化為負無窮
return memorizeCutRodAux(p, n, r)
}
memorizeCutRodAux(p, n, r) {
if r[n] >= 0
return r[n]
if n == 0
q = 0
else q = [email protected] // 初始化為負無窮
for i = 1 to n
q = max(q, p[i] + memorizeCutRodAux(p, n - i, r))
r[n] = q
return q
}
bottomUpCutRod(p, n) {
let r[0...n] be a new array
r[0] = 0
for j = 1 to n
q = [email protected] // 初始化為負無窮
for i = 1 to j
q = max(q, p[i] + r[j - i])
r[j] = q
return r[n]
}
合併後的最終求解方案
記錄最佳cut的方案
extendedBottomUpCutRod(p, n) {
let r[0...n] and s[0...n] be a new array
r[0] = 0
for j = 1 to n //length of rod
q = [email protected]
for i = 1 to j // highest price to cut when length is j
if(q < p[i] + r[j - i])
q = p[i] + r[j - i]
s[j] = i //best place to cut when length is j
r[j] = q
return r[n]
}