1. 程式人生 > >動態規劃學習-【0-1揹包問題】

動態規劃學習-【0-1揹包問題】

題目描述:

問題:0-1揹包問題

描述:有一個揹包,它的容量為C(Capacity),現在有n種不同的物品編號分別為0...n-1,其中每一件物品的重量為w(i),價值為v(i)。問可以向這個揹包中盛放哪些物品,使得在不超過揹包容量的基礎上,物品的總價值最大。

解題思路:

(1)暴力解法:

每一件物品都可以放進揹包,也可以不放進揹包,有2^{n}種情況。我們再從這2^{n}種情形中選出總價值最大的物品,時間複雜度為O(2^{n}*n)。

(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)動態規劃方法實現

待補充。