《背包九讲》 阅读笔记
《背包九講》 閱讀筆記
? 背包問題是動態規劃中非常經典的問題,其題目大致描述為:有N件物品和一個容量為V的背包,第 i 件物品的體積為 c[i], 價值為 w[i]。求解如何裝入可使背包中物品價值最大。
一、01背包
基本思路:
? 01背包表示這N件物品每個都只能拿0次或者1次。01背包是所有背包問題的基石。設F[i, v] 表示從前 i 件物品中選擇一些放入容量為 v 背包所能得到的最大價值,那么可以得到狀態轉移方程為:
? 在第 i 件物品體積 c[i] 沒有超過背包容量 v 的情況下,要考慮的就是第 i 件物品放與不放的情況。若不放就轉化為前 i-1 件物品放入容量 v 背包所能取得的最大價值;若放就轉化為前 i-1 件物品放入 容量 v - c[i] 背包所能取得的最大價值加上第 i 件物品價值w[i]。
? 邊界條件為:
? 這樣,創建二維數組F,逐行計算后,F[N, V] 即為所求。
優化思路:但可以注意到,每次計算的結果僅依賴于上一行的當前列和左側某列兩個元素,并且最終結果是最后一行的最后一個元素,所以只需要創建一個一維數組,計算每行時從后往前覆蓋,將空間復雜度優化為 O(V),偽代碼為:
for i=1..N
for v=V..0
f[v]=max{f[v],f[v-c[i]]+w[i]};
二、完全背包
? 完全背包表示這 N 個物品每個可以拿無數次。完全背包有兩種思路:
基本思路:由于背包容量的限制,每種物品其實最多拿 n[i] = V / c[i] 次,將這 n[i] 個物品展開,其實就形成了一個的01背包,因為01背包問題本身其實沒有限制 N 件物品必須不同。
優化:
? a. 每件物品都可以拿多次,那么我們可以只要那些“物美價廉”的物品,即如果一個物品比其他所有相同體積的物品價值都要高或者同價值但體積最小,就可以將其他物品排除不做考慮。
? b. 第 i 個物品不用展開為 n[i] 個,而是 1 2 4 .. 2^k k = 個體積和價值都為原來 2^k 倍的物品,這樣不管是取多少個,都可以由這些合并而來,于是優化為了一個 的01背包。
優化思路:不用轉化為完全背包,對于第 i 件物品分為一件都不取和至少取一件兩種情況討論,于是狀態轉移方程為
邊界條件與 01 背包時相同
做空間復雜度優化時,可以注意到二維數組元素的計算僅依賴于上一行的當前列和當前行的左側某列兩個元素,所以創建一個一維數組,計算時從前往后覆蓋寫,最后代碼剛好和01背包僅在 v 的循環順序上相反,偽代碼如下
for i=1..N
for v=0..V
f[v]=max{f[v],f[v-c[i]]+w[i]};
三、多重背包
? 多重背包限制第 i 件商品最多拿 m[i] 個
基本思路:同樣是將 m[i] 個物品展開,最后變成一個01背包問題,同樣可以使用完全背包中的 1.b 的優化。
優化思路:對于 m[i] * c[i] >= V 的物品實際上等同于無限,對于這些物品可以不用展開,當作無線背包物品處理即可,即在內層循環時 v 從 0 到 V。
四、混合背包
? 混合背包即有的物品只有一次,有的無限次,有的限制 m[i] 次。
? 如果是01背包和完全背包的混合,那么處理時只需要對不同類型的物品在內存循環時分別采用正序和倒序即可,偽代碼為
for i=1..N
if 第i件物品是01背包
for v=V..0
f[v]=max{f[v],f[v-c[i]]+w[i]};
else if 第i件物品是完全背包
for v=0..V
f[v]=max{f[v],f[v-c[i]]+w[i]};
? 如果混入了多重背包,按照多重背包的思路處理即可。
五、二維費用背包
? 二維費用背包,即背包有兩個維度的限制。如重量和容量,第 i 件物品的重量為 h[i],背包最大承重 B。熟悉了二維背包也就熟悉了N維背包。
基本思路:如果是01背包限制多了一維,那么狀態也對應多一維即可,此時狀態轉移方程為:
優化思路:同樣是對空間復雜度進行優化,使用一個二維數組存儲狀態。
六、分組背包
? 分組背包是指這 N 件物品被分為 K 組,每個組只能取其中一個物品。
基本思路:使用 F[k, v] 表示,從前 k 組取物品,背包容量為 v 情況下背包所能裝下的最大價值。那么解決的思路同樣是考慮當前組不取和當前組取一個(需要進行比較,選出可取出的最大價值),狀態轉移方程為:
邊界條件為:F[0,v] = 0 ,偽代碼為
for 所有的組k
for v=V..0
for 所有的i屬于組k
f[k][v]=max{f[k][v],f[k-1][v],f[k-1][v-c[i]]+w[i]}
優化思路:同樣是在空間復雜度上進行優化,但要額外注意的是使用二維數組存儲狀態時 v 和 i 的循環先后可以調換,而使用一維數組存儲狀態時循環必須是先 v 后 i,原因是對于一個 v 要從該組所有的 i 中選出最優的一個才能進行下一個元素的計算,否則同組之間元素將相互影響,具體代碼可以參考:分組背包循環順序對結果的影響, 偽代碼為:
for 所有的組k
for v=V..0
for 所有的i屬于組k
f[v]=max{f[v],f[v-c[i]]+w[i]}
七、其他
? 對于有依賴的背包問題和泛化物品力有未逮,不在此記錄。
? leetcode的背包問題:
? 01背包:494. 目標和、416. 分割等和子集、1049. 最后一塊石頭的重量 II
? 完全背包:322. 零錢兌換、279. 完全平方數、518. 零錢兌換 II、377. 組合總和 Ⅳ
? 多維背包:474. 一和零、879. 盈利計劃
? 分組背包:1155. 擲骰子的N種方法
?
參考資料
- [1] 背包九講第二版
- [2] dd大牛的《背包九講
總結
以上是生活随笔為你收集整理的《背包九讲》 阅读笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win10怎么设置U盘禁止拷贝文件 wi
- 下一篇: Mysql配置查询