幾道動態規劃題目
阿新 • • 發佈:2018-11-29
幾道常見的動態規劃題
通常暴力窮舉的方式是一種糟糕的策略,動態規劃正是一種解決類似問題的思想,如果一個問題滿足最優子結構,就可以通過把原問題可以分解為幾個子問題來解決,即全域性的最優解一定是某個區域性的最優解,我們需要一張表來儲存前一次計算的結果,以便遞推出原問題的解,這樣可以避免重複計算。
0-1揹包
固定容量的揹包,希望能夠裝入價值最大的物品。假設 是揹包容量為 ,可選擇物品為0~i時0-1 揹包問題的最優值。 為第i個物品的容量, 為第i個物品的價值。
- 當i=0時,表示沒有可選擇的物品,總價值為0。
- 當j=0時,表示揹包容量為0,不好裝東西,總價值為0。
- 當 時,可以選擇放入物品i或不放入物品i,若不放入物品i,則只剩下i-1個物品可以選擇,揹包容量仍為j,若放入物品i,也只剩下i-1個物品可供選擇,揹包剩餘容量為 。
- 當 時,揹包放不下物品i,只能在剩餘i-1個物品中選擇。
遞推式:
程式碼:
import numpy as np
def knapsack(c, w, v):
assert len(w)==len(v)
m = np.full((len(w) + 1, c + 1), -1)
m[0,:] = 0 # i=0
m[:, 0] = 0 # j=0
for i in range(1, len(w) + 1):
for j in range(1, c + 1):
if w[i - 1] > j:
m[i, j] = m[i-1, j]
else:
m[i, j] = max(m[i-1, j], m[i-1, j-w[i - 1]] + v[i - 1])
print(m)
# solution
j = c
x = np.full(len(w), -1)
for i in range(len(w)):
if m[i+1, j] == m[i, j]:
x[i] = 0
else:
x[i] = 1
j = j - w[i]
return x
c = 10 # 揹包容量
w = [2,2,6,5,4] # 物品容量
v = [6,3,5,4,6] # 物品價值
s = knapsack(c, w, v)
print(s)
[[ 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 6 6 6 6 6 6 6 6 6]
[ 0 0 6 6 9 9 9 9 9 9 9]
[ 0 0 6 6 9 9 9 9 11 11 14]
[ 0 0 6 6 9 9 9 10 11 13 14]
[ 0 0 6 6 9 9 12 12 15 15 15]]
[1 1 0 0 1]
可見,最大價值為15,選擇第0個、第1個以及第4個物品。
最小編輯距離
給出兩個單詞source和target,求出刪除、替換或插入某個字元使得source變為target的最少次數。
例如:source=‘intention’, target=‘execution’,最少次數為5,總共有5步。
- intention -> inention (刪除 ‘t’)
- inention -> enention (將 ‘i’ 替換為 ‘e’)
- enention -> exention (將 ‘n’ 替換為 ‘x’)
- exention -> exection (將 ‘n’ 替換為 ‘c’)
- exection -> execution (插入 ‘u’)
假設 為source的第0到i個字元與target的第0到j個字元分別組成的字串的最小編輯距離。
- 當 時,兩個都為空串,距離為0。
- 當 時,插入j次就行,距離為j。
- 當 時,刪除i次就行,距離為i。
- 當 時,看是否新增source的第i個字元或刪除target的第j個字元能否使得剩餘部分相同,即繼續計算 或 ,如果新增或刪除後還不等,則需要繼續計算 ,我們取最小的情況。
遞推式: