作為一名演算法愛好者,遇到問題總希望找到最優的解決方案,作為一名工程師,卻需要在頻繁變更的需求中快速給出響應。在最快和最優中,往往需要找到一種平衡。筆者在最近的工作中有所感悟,以動態規劃中經典的鋼條切割問題為例,在此記錄一二。
給定一段長度為
n n
英吋的鋼條和乙個**表pi
(i=1
,2,.
..,m
,m≤n
)' role="presentation" style="position: relative;">pi(
i=1,
2,..
.,m,
m≤n)
pi(i
=1,2
,...
,m,m
≤n),求切割鋼條方案,使得銷售收益rn
r
n最大。下圖給出了**樣例:長度1
2345
6789
10**15
891017
1720
2430
本題是《演算法導論》中動態規劃這一章的經典問題,相關的解法已經很成熟了。這裡直接上**
def
dp_solver
(num_rods):
defmemoized_cut_rod_aux
(p, n, r):
if r[n-1] >= 0:
return r[n-1]
q = 0
if n > 0:
q = -1
for i in range(1, min(len(p)+1, n+1)):
q = max(q, p[i-1] + memoized_cut_rod_aux(p, n-i, r))
r[n-1] = q
return q
p = [1.0, 5.0, 8.0, 9.0, 10.0, 17.0, 17.0, 20.0, 24.0, 30.0]
r = [-1] * num_rods
res = memoized_cut_rod_aux(p, num_rods, r)
print('dp optimal objective value = %d' % res)
如果將鋼條切割問題看成是帶約束的整數優化問題,那麼可以給出如下表示式
maxobj
=ptx
s.t.
atx=
n,xj
∈n,i
=1,2
,3…,
m.maxob
j=pt
xs.t
.atx
=n,x
j∈n,
i=1,
2,3…
,m
.其中 p=
[1,5
,8,9
,10,17
,17,20
,24,30
] p=[1
,5,8
,9,10
,17,17
,20,24
,30]a=
[1,2
,3,4
,5,6
,7,8
,9,10
] a=[1
,2,3
,4,5
,6,7
,8,9
,10
]使用google開源的第三方庫or-tools,可以給出如下**
from __future__ import print_function
from ortools.linear_solver import pywraplp
defip_solver
(num_rods):
list_length = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
list_price = [1.0, 5.0, 8.0, 9.0, 10.0, 17.0, 17.0, 20.0, 24.0, 30.0]
solver = pywraplp.solver('solveintegerproblem',
pywraplp.solver.cbc_mixed_integer_programming)
objective = solver.objective()
rods = * len(list_length)
for i, length in enumerate(list_length):
rods[i] = solver.intvar(0.0, solver.infinity(), 'x_'+str(length))
objective.setcoefficient(rods[i], list_price[i])
objective.setmaximization()
constraint = solver.constraint(num_rods, num_rods)
for i, length in enumerate(list_length):
constraint.setcoefficient(rods[i], length)
"""solve the problem and print the solution."""
result_status = solver.solve()
print('ip optimal objective value = %d' % solver.objective().value())
在鋼條切割這個具體問題下,簡單分析這兩種演算法的優劣。
動態規劃可以看做是乙個量身定做的解法,它的效率無疑是最高的。然而缺點在於,如果增加需求,則需要調整甚至重構**。比如說,需要考慮切割工序的成本,或者是限制某種長度的鋼條個數,或者是
n n
太大以至於超過了遞迴棧的最大深度,這些都需要對**進行調整。從工程角度來說,在需求頻繁變動的情況下,沒有經驗的工程師會難以根據變動快速迭代,給出解決方案。
整數規劃可以看做是將某種定義更為廣泛的問題運用到乙個特殊場景。它的效率遠遠不如動態規劃。然而整數規劃的好處在於兩點。第一點,需求變更後無需調整**結構,只需改動模型本身;第二點,作為乙個成熟的輪子,不需要考慮問題規模擴大後帶來的各種問題。
在業務發展前期,需求變更後快速響應的要求遠大於對**效率的要求,整數規劃不失為一種應急的解決方案。在業務發展相對成熟,需求穩定之後,再針對問題量身定製解決方案。
動態規劃 鋼條切割
一家公司購買長鋼條,將其切割成短鋼條 切割本身沒有成本,長度為i的短鋼條的 為pi。那給定一段長度為n的鋼條和乙個 表pi,求鋼條的切割方案使得收益rn最大。如乙個pi如下 長度i12 3456 78910 pi15 891017 1720 2430 在距離鋼條左端i長度處,我們總是可以選擇切割或者...
動態規劃 鋼條切割
這是演算法導論動態規劃的乙個例子,自己實現了一下 給定乙個長度為n英吋的鋼條和乙個 表pi i 1,2 n 求切割鋼條方案,使得銷售收益rn最大。注意,如果長度為n的鋼條 pn足夠大,則最優解可能就不需要切割。分析 如下 include include include using namespace...
動態規劃 鋼條切割
動態規劃 dynamic programming 什麼是動態規劃,我們要如何描述它?動態規劃演算法通常基於乙個遞推公式及乙個或多個初始狀態。當前子問題的解將由上一次子問題的解推出。動態規劃和分治法相似,都是通過組合子問題的解來求解原問題。分治法將問題劃分成互不相交的子問題,遞迴求解子問題,再將他們的...