動態規劃python版
阿新 • • 發佈:2018-12-10
一 動態規劃
動態規劃問題是面試題中的熱門話題,如果要求一個問題的最優解(通常是最大值或者最小值),而且該問題能夠分解成若干個子問題,並且小問題之間也存在重疊的子問題,則考慮採用動態規劃。
使用動態規劃特徵: 1. 求一個問題的最優解 2. 大問題可以分解為子問題,子問題還有重疊的更小的子問題 3. 整體問題最優解取決於子問題的最優解(狀態轉移方程) 4. 從上往下分析問題,從下往上解決問題 5. 討論底層的邊界問題
例項1 剪繩子問題 給你一根長度為N的繩子,請把繩子剪成M段(m,n都是整數),每段繩子的 長度記為k[0],k[1],k[2]…. 請問如何剪繩子使得k[0],k[1],k[2] 的乘積最大 例如 繩子長度8 最大乘積18 = 2*3*3
def jianshengzi(n): # 先對邊界問題進行求解,因為明顯剪的值小於不剪的值 # 則提出先討論這三種情況 if n < 2: return 0 if n == 2: return 1 #長度為2,只能剪成1*1 if n == 3: return 2 #長度為3,剪成2*1 > 1*1*1 #若繩子長於4呢,申請一個長度為50的陣列 #羅列出切割的邊界問題 h = [0]*50 h[0] = 0 h[1] = 1 h[2] = 2 h[3] = 3 # 遞迴問題是 f(n) = max{f(i)*f(n-i)} for i in range(4,n+1): maxs = 0 for j in range(1,i/2+1): mult = h[j] * h[i-j] if maxs < mult: maxs = mult h[i] = maxs # 每次J的迭代輪詢出該長度的最大值 print h return h[n] print jianshengzi(8)
例項2 硬幣問題 我們有面值為1元3元5元的硬幣若干枚,如何用最少的硬幣湊夠11元? 分析: 1 求問題的最優解:最小的硬幣數 2 是否有子問題:f(n)表示的最少硬幣數是是上一次拿時候的硬幣數最少。 注意:f(n)是n元的最小硬幣數,最後一次可拿的硬幣數為1,3,5 則下一步 的最小硬幣數為 f(n-vi) 它的狀態變更不是按元數的,是按照上次拿的硬幣錢目 3 狀態轉移方程為 f(n)= min(f(n-vi)+1) 4 邊界問題(找到最後一個重複的問題) 這裡 f(1)=1 ,f(2)=f(1)+f(1)=2 f(3)=min(1,f(2)+1) f(4)=f(3)+1 f(5)=1 5 從上往下分析問題,從下往上解決問題。
def f(n):
if n == 1: #把所有的邊界問題找到
return 1
if n == 2:
return 2
if n == 3:
return 1
if n == 4:
return 2
if n == 5:
return 1
h = [1,3,5]
minx = n
for i in range(3):
coun = f(n-h[i])+1 # 採用了遞迴的思想 這裡是從上到下,
if minx > coun: # 複雜度比較高
minx = coun
return minx
print f(11)
def f(n):
if n == 1:
return 1
if n == 2:
return 2
if n == 3:
return 1
if n == 4:
return 2
if n == 5:
return 1
h = [1,3,5]
for x in range(6,n+1): #從下往上的思維解決
minx = n
for i in range(3):
coun = f(x-h[i])+1 #從下往上的思維解決
if minx > coun:
minx = coun
return minx
print f(11)