動態規劃學習-【0-1揹包問題】
題目描述:
問題:0-1揹包問題
描述:有一個揹包,它的容量為C(Capacity),現在有n種不同的物品編號分別為0...n-1,其中每一件物品的重量為w(i),價值為v(i)。問可以向這個揹包中盛放哪些物品,使得在不超過揹包容量的基礎上,物品的總價值最大。
解題思路:
(1)暴力解法:
每一件物品都可以放進揹包,也可以不放進揹包,有種情況。我們再從這種情形中選出總價值最大的物品,時間複雜度為O()。
(2)貪心演算法解法:
貪心演算法:用物品的價值除以重量得到單位物品的價值。貪心演算法就是優先放入平均價值最高的物品。
第0件物品的單位價值為6,第1件物品的單位價值為5,第2件物品的單位價值為4。我們首先放單位價值最高的物品0號,它的重量是1。接著放入單位價值次大的物品1號,它的重量是2,。揹包中還能容下2個重量,由於編號為2的物品重量是3,所以不能放入到揹包中。所以貪心演算法得到的揹包中最多能容納16價值的物品。
很明顯,對於這個問題,我們只放入編號為1和2的物品,總價值是最大的。與貪心演算法恰恰相反的是,我們剛好放棄了單位價值最大的編號為0的商品。所以這個例子證明,貪心演算法是無法解決這樣的問題。
(3)動態規劃解法:
動態規劃解題思路:
1. 狀態轉移方程:
之前接觸到的動態規劃題目涉及到的狀態都可以用一個變數(或者引數)解決問題。通常問題中含有的引數,決定了問題需要滿足的約束條件。對於當前的揹包問題,也是求一個最優解的問題。對於這個問題,我們兩個約束條件,第一個約束條件是在n個物體裡選擇,第二個約束條件是選定的容量要小於等於給定的C值。求解價值最大的函式設為F(n, C),F函式傳入兩個引數n和C。F(n,C)函式的定義是:考慮將n個物品放進容器為C的揹包,使得價值最大。
我們知道問題的狀態轉移方程之後,可以使用自頂向下的方式(遞迴法)解決這個問題;也可以對遞迴法進行優化使用記憶化搜尋的方式解決這個問題;最後我們寫出自底向上的動態規劃解法。
1)遞迴方法實現
class Solution: def knapsack01(self, w, v, C): return self.bestValue(w, v, len(w)-1, C) def bestValue(self, w, v, index, C): if index < 0 or C <= 0: return 0 res = self.bestValue(w, v, index - 1, C) if C >= w[index]: res = max(res, v[index] + self.bestValue(w, v, index - 1, C - w[index])) return res solution = Solution() w = [1, 2, 3] v = [6, 10, 12] print(solution.knapsack01(w, v, 5))
2)記憶化搜尋方法實現
待補充。
3)動態規劃方法實現
待補充。