125. 揹包問題 II

寫在前面,如果有更好的方法可以給博主分享一下麼,木有vip,看不到lintcode的題解,謝謝啦

題目描述:

lintcode: https://www.lintcode.com/problem/backpack-ii/description

上一篇揹包問題:https://blog.csdn.net/qq_xuanshuang/article/details/104025707

有 n 個物品和一個大小爲 m 的揹包. 給定數組 A 表示每個物品的大小和數組 V 表示每個物品的價值.

問最多能裝入揹包的總價值是多大?

樣例:

輸入:m = 10, A = [2, 3, 5, 7], V = [1, 5, 2, 4]

輸出: 9 

解釋:裝入A[1]和A[3]可以得到最大價值,V[1] + V[3] = 9

挑戰

O(nm) 空間複雜度可以通過, 不過你可以嘗試 O(m) 空間複雜度嗎?

注意事項

  1. A[i], V[i], n, m 均爲整數

  2. 你不能將物品進行切分

  3. 你所挑選的要裝入揹包的物品的總大小不能超過 m

  4. 每個物品只能取一次

題解

方法一:遞歸

暴力求解所有可能性,自頂向下

_helper(self, w, v, index, c)函數,表示考慮求解將[0,index]的物品放入揹包中,能得出的最大價值(其實這一題和上一題幾乎完全一樣,可以將該題的價值v想象成重量A,求最大價值對應上題的求最大容量),遞歸函數f(index, c)=max( f(index - 1,c), f(index - 1, c - w[i]) + v[i] ),其中index,表示考慮將[0, index]的物品放入容量爲c的揹包,c-表示剩餘容量,故f(len(A) - 1, m)是最終結果,其表示將所有物品考慮放入容量爲m的揹包中的最大價值。

class Solution:
    """
    @param m: An integer m denotes the size of a backpack
    @param A: Given n items with size A[i]
    @param V: Given n items with value V[i]
    @return: The maximum value
    """
    def backPackII(self, m, A, V):
        if not A or len(A) != len(V) or m <= 0:
            return 0
        return self._helper(A, V, len(A) - 1, m)

    def _helper(self, w, v, index, c):
        if index < 0 or c < 0:
            return 0
        res = 0
        for i in range(0, index + 1):
            res = max(res, self._helper(w, v, i - 1, c))
            if c - w[i] >= 0:
                res = max(res, self._helper(w, v, i - 1, c - w[i]) + v[i])
        return res

方法二:記憶化搜索

水到渠成的記憶化搜索

class Solution:
    def __init__(self):
        self.memo = []

    def backPackII(self, m, A, V):
        if not A or len(A) != len(V) or m <= 0:
            return 0
        self.memo = [[-1] * (m + 1) for _ in range(len(A))]
        return self._helper(A, V, len(A) - 1, m)

    def _helper(self, w, v, index, c):
        if index < 0 or c < 0:
            return 0
        if self.memo[index][c] != -1:
            return self.memo[index][c]
        res = 0
        for i in range(0, index + 1):
            res = max(res, self._helper(w, v, i - 1, c))
            if c - w[i] >= 0:
                res = max(res, self._helper(w, v, i - 1, c - w[i]) + v[i])
        self.memo[index][c] = res
        return res

方法三:動態規劃

class Solution:
    def backPackII(self, m, A, V):
        if not A or len(A) != len(V) or m <= 0:
            return 0
        dp = [[0] * (m + 1) for _ in range(len(A))]
        for j in range(m + 1):
            if j >= A[0]:
                dp[0][j] = V[0]

        for i in range(1, len(A)):
            for j in range(m + 1):
                dp[i][j] = dp[i-1][j]
                if j >= A[i]:
                    dp[i][j] = max(dp[i][j], dp[i-1][j - A[i]] + V[i])
        return dp[-1][-1]

空間優化

class Solution:
    def backPackII(self, m, A, V):
        if not A or len(A) != len(V) or m <= 0:
            return 0
        dp = [0] * (m + 1)

        for i in range(0, len(A)):
            j = m
            while j >= A[i]:
                dp[j] = max(dp[j], dp[j - A[i]] + V[i])
                j -= 1
        return dp[-1]

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章