動態規劃,從例子到理解

2021-08-31 16:10:15 字數 4412 閱讀 7986

1、問題建模:得到優化的目標函式,約束條件?

2、劃分子問題:明確問題的規模在**?哪些維度的規模,這樣才能才會劃分子問題,注意邊界。

3、得到遞推方程:可以巨集觀的考慮,也可以借助於微觀的歸納演繹。

4、然後檢測是否滿足最優子結構:檢查子問題對其子問題的始、終點也是最優的序列。

5、最小問題的界定,確定初值。

一般得到了遞推方程,就可以寫出基於遞迴的**實現。

假如子問題大量的重複計算,可借助於遞迴樹分析,就要考慮動態規劃。

一般可基於兩種方式實現動態規劃:一是基於自頂向下的備忘模型,二是基於自底向上演繹模型。

1、標記哪些子問題結果已經計畫出來了沒,計算出來了就直接用,

2、特點是**簡單,可以直接基於遞迴的**修改,可能比自底向上演繹模型更節省運算,因為沒有用到的子問題沒有必要計算,

3、缺點是追蹤解可能需要專門設計或者不好實現,自頂向下的備忘模型追蹤解我還要總結一番。

1、從小到大的子問題依次計算;

2、前面的計算結果,後面會用到,所以備忘**初值很重要;

3、類似於數學歸納法,從已知到未知,演繹推理;

4、演繹推理過程,可以標記路徑,追蹤解比較容易實現;

5、缺點:並不是最大規模以下的所有子問題都需要計算。

#%%

# house gold

defhouse_gold_rec

(gold,n)

:if n ==0:

return gold[0]

if n ==1:

return gold[gold[0]

] first = gold[n]

+house_gold_rec(gold,n-2)

second = house_gold_rec(gold,n-1)

return

(first,second)

[firstdefhouse_gold_top_down_

(gold)

: n =

len(gold)

list=[

-1]*

(n)list[0

]= gold[0]

list[1

]= gold[gold[0]

]def

house_gold_top_down

(gold,n):if

list

[n]==-1

: first = gold[n]

+house_gold_top_down(gold,n-2)

second = house_gold_top_down(gold,n-1)

list

[n]=

(first,second)

[firstreturn

list

[n]return house_gold_top_down(gold,n-1)

defhouse_gold_bottom_up

(gold)

: n =

len(gold)

list

=[gold[0]

,gold[gold[0]

]]for i in

range(2

,n):

first = gold[i]

+list

[i-2

] second =

list

[i-1

]list

(first,second)

[first)return

list

[n-1

]#%%

gold =[10

,28,5

,77,5

,10,99

,88,67

]#%%

print house_gold_rec(gold,

len(gold)-1

)#%%

print house_gold_top_down_(gold)

#%%print house_gold_bottom_up(gold)

gold =[10

,28,5

,77,5

,10,99

,88,67

]print house_gold_rec(gold,

len(gold)-1

)271

print house_gold_top_down_(gold)

271print house_gold_bottom_up(gold)

271

#%%

#coin change

defcoins_change_rec

(money,coins)

:if money ==0:

return

0 result =

1000

for i in

range

(len

(coins)):

if money >= coins[i]

: first = coins_change_rec(money-coins[i]

,coins)

result =

(first,result)

[first>result]

result +=

1return result

defcoins_change_top_down_

(money,coins)

:list=[

-1]*

(money+1)

list[0

]=0def

coins_change_top_down

(money,coins)

: result =

10000

for i in

range

(len

(coins)):

if money >= coins[i]:if

list

[money-coins[i]]==

-1:list

[money-coins[i]

]= coins_change_top_down(money-coins[i]

,coins)

result =

(list

[money-coins[i]

],result)

[list

[money-coins[i]

]>result]

list

[money]

= result +

1return

list

[money]

coins_change_top_down(money,coins)

print

list

return

list

[money]

defcoins_change_bottom_up

(money,coins)

:list=[

0,]

min_ =

min(coins)

for x in

range(1

,min_)

:list

10000

)list1)

for j in

range

(min_+

1,money+1)

: result =

10000

for i in

range

(len

(coins)):

if j >= coins[i]

: result =

(list

[j-coins[i]

],result)

[list

[j-coins[i]

]>result]

list1)

print

list

return

list

[money]

#%%

coins =[13

,11,19

,23,29

,66,46

,90]money =

101print coins_change_rec(money,coins)

print coins_change_top_down_(money,coins)

print coins_change_bottom_up(money,coins)22

2

動態規劃例子

對於由從1到n 1 n 39 這n個連續的整數組成的集合來說,我們有時可以將集合分成兩個部分和相同的子集合。例如,n 3時,可以將集合 分為和。此時稱有一種方式 即與順序無關 n 7時,共有四種方式可以將集合 分為兩個部分和相同的子集合 和 和 和 和 輸入 程式從標準輸入讀入資料,只有一組測試用例...

動態規劃例子

演算法描述 已知多段圖的鄰接表,利用從後往前遞推的方法,先從最後一層往前保留當前的最短路徑長度,由子結構的最優解得到原問題的最優解。遞推公式是 cost i,j min 這裡為了節約空間,用一維陣列cost來儲存節點j到t的最短路徑長度。將所有節點按0 n 1進行編號,源點s為0,匯點t為n 1 向...

從DFS到記憶化DFS到動態規劃

什麼是動態規劃?動態規劃 dynamic programming 是通過組合子問題的解來解決問題的。動態規劃是用於求解包含重疊子問題的最優化問題的方法。其基本思想是,將原問題分解為相似的子問題。在求解的過程中通過子問題的解求出原問題的解。動態規劃的分類 1.線性規劃 攔截飛彈,合唱隊形,挖地雷等。2...