动态规划法(五)钢条切割问题(rod cutting problem)
??繼續(xù)講故事~~
??我們的主人公現(xiàn)在已經(jīng)告別了生于斯,長于斯的故鄉(xiāng),來到了全國最大的城市S市。這座S市,位于國家的東南部,是全國的經(jīng)濟(jì)中心,工商業(yè)極為發(fā)達(dá),是這個國家的人民所向往的城市。這個到處都留著奶與蜜的城市,讓丁丁充滿了好奇感和新鮮感,他多想好好觸摸這個城市的脈搏啊!
??這不,他此刻正走在城市的某高新園區(qū),不遠(yuǎn)處傳來鋼條切割的聲音。他好奇地走上前去,看著工人們正在熟練地切割鋼條,并打包完成包裝。此時,一位工人看到了丁丁,一看,竟是自己的同鄉(xiāng)。他熱情地上去打了招呼,并詢問了鄉(xiāng)下的情況,他倆約了中午一起吃飯。
??午飯時,老鄉(xiāng)熱情地請丁丁在園區(qū)最好的飯店吃飯,他倆聊得也很開心。突然,老鄉(xiāng)想到了丁丁學(xué)過計算機(jī)方面的理論,于是他準(zhǔn)備把自己最近遇到的問題告訴丁丁,看看他能不能解決。
鋼條切割問題: 給定一段長度為n英寸的鋼條和一個價格表(p_i(i=1,2,...,n)),求切割鋼條方案,使得銷售收益(R_n)最大。注意,如果長度為n英寸的鋼條的價格(p_n)足夠大,最優(yōu)解可能就是完全不需要切割。
已知鋼條價格表如下:
??聽到老鄉(xiāng)正在為整個問題發(fā)愁,丁丁內(nèi)心也想著嘗試解決這個問題。毫無疑問,這個問題也是可以用動態(tài)規(guī)劃法解決的,于是,他拿出稿紙推演起來:
將鋼條從左邊切割下長度為i的一段,只對右邊剩下的長度為n-i的一段繼續(xù)進(jìn)行切割(遞歸求解),對左邊的一段則不再進(jìn)行切割。這樣,不做任何切割的方案可以描述為:第一段長度為n,收益為pn,剩余部分長度為0,對應(yīng)的收益為(R_0)=0。于是,我們就得到該問題的求解公式:
[R_n=minlimits_{1leq i leq n}(p_n+R_n-1)
]
采用自底向上法(bottom-up method)來求解該問題,需要用一個列表來記錄收益(r_n),一個列表來記錄切割方案,其Python代碼如下:
import time
# 使用動態(tài)規(guī)劃法(dynamic programming)解決鋼條切割問題
# 鋼條長度與對應(yīng)的收益
length = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
profit = (1, 5, 8, 9, 10, 17, 17, 20, 24, 30)
# 動態(tài)歸納法,自底向上的CUT-ROD過程,加入備忘機(jī)制
# 運(yùn)行時間: 多項(xiàng)式
# 參數(shù):profit: 收益列表, n: 鋼條總長度
# 返回參數(shù): q: 最大收益
def bottom_up_cut_rod(profit, n):
r = [0] # 收益列表
s = [0]*(n+1) # 切割方案列表
for j in range(1, n+1):
q = float('-inf')
for i in range(1, j+1):
if max(q, profit[length.index(i)]+r[j-i]) == profit[length.index(i)]+r[j-i]:
s[j] = i
q = max(q, profit[length.index(i)]+r[j-i])
r.append(q)
return r[n], s[n]
# method of how to cut the rod
def rod_cut_method(profit, n):
how = []
while n != 0:
t,s = bottom_up_cut_rod(profit, n)
how.append(s)
n -= s
return how
for i in range(1, 11):
t1 = time.time()
money,s = bottom_up_cut_rod(profit, i)
how = rod_cut_method(profit, i)
t2 = time.time()
print('profit of %d is %d. Cost time is %ss.'%(i, money, t2-t1))
print('Cut rod method:%s
'%how)
輸出結(jié)果:
profit of 1 is 1. Cost time is 0.0s.
Cut rod method:[1]
profit of 2 is 5. Cost time is 0.0s.
Cut rod method:[2]
profit of 3 is 8. Cost time is 0.0s.
Cut rod method:[3]
profit of 4 is 10. Cost time is 0.0s.
Cut rod method:[2, 2]
profit of 5 is 13. Cost time is 0.0s.
Cut rod method:[3, 2]
profit of 6 is 17. Cost time is 0.0s.
Cut rod method:[6]
profit of 7 is 18. Cost time is 0.0s.
Cut rod method:[6, 1]
profit of 8 is 22. Cost time is 0.0005009174346923828s.
Cut rod method:[6, 2]
profit of 9 is 25. Cost time is 0.0s.
Cut rod method:[6, 3]
profit of 10 is 30. Cost time is 0.0s.
Cut rod method:[10]
不一會兒他就搞定了這個問題,他將不同長度的鋼條所能獲得最大收益和對應(yīng)的切割方案告訴了老鄉(xiāng)。老鄉(xiāng)聽后大喜,他為丁丁解決了這個困擾它們公司長久的問題而感到由衷高興,有了以上的結(jié)果,那么,鋼條的長度再長也不是問題了。
??午飯后,老鄉(xiāng)將剛才吃飯時丁丁的解決方法告訴了老板,老板也是喜出望外,他決定高薪聘請這個年輕人。而我們的丁丁,他早已離開高新區(qū),向著下一個目的地出發(fā)了~~
注意:本人現(xiàn)已開通兩個微信公眾號: 用Python做數(shù)學(xué)(微信號為:python_math)以及輕松學(xué)會Python爬蟲(微信號為:easy_web_scrape), 歡迎大家關(guān)注哦~~
總結(jié)
以上是生活随笔為你收集整理的动态规划法(五)钢条切割问题(rod cutting problem)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# socket编程 使用fleck轻
- 下一篇: SQL Plus的使用详解(登录和常用命