動態規劃 鋼條切割問題

2021-10-01 21:38:53 字數 2007 閱讀 2439

給定一段長度為n英吋的鋼條和乙個**表p,求切割鋼條方案(鋼條的長度均為整英吋),使得銷售收益最大。

我們可以計算出長度為n英吋的鋼條共有2的(n-1)次方種不同的切割方案。

為解決規模為n的原問題,我們可以這樣考慮。先求解形式完全一樣,但規模更小的子問題。我們將鋼條左邊切割下長度為i的一段(i的取值範圍是[1, n]),然後只對右邊剩下的長度為n-i的一段繼續進行切割(遞迴求解)。即問題的分解方式為:將長度為n的鋼條分解為左邊開始一段,以及剩餘部分繼續分解的結果。這樣我們就可以做出如下解答:

function

cut_rod

(p, n)

return sum;

}let p =[0

,1,5

,8,9

,10,17

,17,20

,24,30

];console.

log(

cut_rod

(p,5))

;//13

然而,以上**一旦輸入規模變大,程式執行時間就會變得相當長。以n=4為例,當我們對整個遞迴過程展開是,它所做的工作量如下:

回過頭看,會發現整個過程進行了大量的重複計算,嚴重浪費了效率。

接下來展示如何將它轉換為乙個更高效的動態規劃演算法。動態規劃方法對每個子問題只求解一次,並將結果儲存下來。如果隨後在此需要此子問題的解,無需重新計算,只需查詢儲存的結果。有兩種方法:

帶備忘的自頂向下法

此方法仍然按照自然的遞迴形式程式設計,但過程中會儲存每個子問題的解。

function

memorized_cut_rod

(p,n)

if(n ==0)

let sum =

-infinity

;for

(let i =

1; i <= n; i++

) arr[n]

= sum;

return sum;

}return

_memorized_cut_rod

(p, n, arr)

}let p =[0

,1,5

,8,9

,10,17

,17,20

,24,30

];console.

log(

memorized_cut_rod

(p,5))

;//13

對照之前的**,動態規劃方法付出了額外的記憶體空間,但是節省了非常多的時間。

自底向上法

這種方法一般需要恰當定義子問題「規模」的概念,使得任何子問題的求解都只依賴於「更小的」子問題的求解。

function

bottom_up_cut_rod

(p, n)

// 陣列中記錄子問題的解

arr[i]

= sum;

}return arr[n];}

let p =[0

,1,5

,8,9

,10,17

,17,20

,24,30

];console.

log(

bottom_up_cut_rod

(p,5))

;//13

此方法採用子問題的自然順序,若j < i,則規模為j的子問題比規模為i的子問題更小,因此,過程依次求解規模為i = 0,1,…,n的子問題。

動態規劃 鋼條切割問題

已知鋼條切割的不同長度對應的不同 如下所示 長度i 1 23 45 67 89 10 pi 1589101717202430 求輸入長度,輸出最佳的收益。詳細理論知識見 演算法導論第十五章 p359 書中給出三個演算法 一 自頂向下遞迴實現 缺點 當n足夠大時,時間會 性地增長。偽 cut rod ...

動態規劃 鋼條切割問題

動態規劃與分治法相似,都是通過組合子問題的解來求解原問題。回顧下分治法的原理 它將問題劃分為互不相交的子問題 注意 互不相交 遞迴求解子問題,再將它們的解組合起來,即為原問題的解。但是,動態規劃與分治法不同,有以下幾點 1 對於子問題重疊的情況,分治法則重複求解,不高效。而動態規劃對每個子問題只求解...

動態規劃 鋼條切割問題

一家公司購買長鋼條,將其切割成短鋼條 切割本身沒有成本,長度為i的短鋼條的 為pi。那給定一段長度為n的鋼條和乙個 表pi,求鋼條的切割方案使得收益rn最大。如乙個pi如下 長度i123 4567 8910 pi15 891017 1720 2430 在距離鋼條左端i長度處,我們總是可以選擇切割或者...