【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...)
背包問題總結
背包問題
背包問題 (Knapsack problem x ) 有很多種版本,常見的是以下三種:
-
0-1 背包問題 (0-1 knapsack problem):每種物品只有一個
-
完全背包問題 (UKP, unbounded knapsack problem):每種物品都有無限個可用
-
多重背包問題 (BKP, bounded knapsack problem):第 i 種物品有 n[i] 個可用
0-1 背包問題
0-1背包中一種物體只有一個,放入數量為0或者1
定義狀態 dp[i][j],表示“
把前 i 種物品裝進重量限制為 j 的背包可以獲得的最大價值
”
v[i]表示物品i的價值,w[i]表示物品i的重量,j為背包的重量限制
0/1背包問題狀態轉移方程便是:
dp[i][j] = max{dp[i − 1][j],
dp[i − 1]
[j − w[i]] + v[i]}
兩項分別代表物品i不選擇或者選擇的情況 (減去的代表選擇的)
時間復雜度是O(nb),空間也是O(nb),假設有n種物品,重量限制為b
可以簡化為:
d[j]=max{d[j],d[j-w[i]]+v[i]};
注意:遍歷j時務必從右到左,因為d[j]只依賴於上一階段的結果,從右到左避免覆蓋上階段有用結果
完全背包問題
完全背包中一種物體可以有多個,可以放滿背包為止
完全背包問題狀態轉移方程是:
dp[i][j] = max{dp[i − 1][j],
dp[i]
[j − w[i]] + v[i]}
兩項分別代表物品i不選擇或者選擇,由於對物品i沒有限制,故后一項為dp[i]而非上面的dp[i-1]
或用以下遞推式(上面的效率要高一點):
dp[i][j] = max( dp[i-1][j-k*w[i]] + k*v[i] ), k為選擇物品的個數, k=0,1,2...j/w[i] (0 ≤ k ∗ w[i] ≤ j)
基於前i-1個物品,在選擇不同個數的物品i的方案中選擇最大的那個
(和問題
coin change 比較相似)
可以簡化為:
d[j] = max{d[j], d[j-k*w[i]] + k*v[i]}
注意:遍歷j時務必從右到左,原因同上
多重背包問題
多重背包中一種物體可以有多個,個數有人為限定(也不能超過背包容量)
多重背包問題狀態轉移方程是:
dp[i][j] = max( dp[i−1][j−k∗w[i]] + k∗v[i] ) 0 ≤ k ≤ n[i],0 ≤ k ∗ w[i] ≤ j
n[i]為物品i限制的個數
基於前i-1個物品,在選擇不同個數的物品i的方案中選擇最大的那個
可以簡化為:
d[j] = max{d[j], d[j-k*w[i]] + k*v[i]}
注意:遍歷j時務必從右到左,原因同上
參考: