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...