Day 37 | 01揹包問題 、416. 分割等和子集

forrestr發表於2024-07-07

01揹包問題 二維dp

https://programmercarl.com/揹包理論基礎01揹包-1.html
影片講解:https://www.bilibili.com/video/BV1cg411g7Y6
有n件物品和一個最多能背重量為w 的揹包。第i件物品的重量是weight[i],得到的價值是value[i] 。每件物品只能用一次,求解將哪些物品裝入揹包裡物品價值總和最大。

思考

dp[i][j] 表示從下標為[0-i]的物品裡任意取,放進容量為j的揹包,價值總和最大是多少。

def test_2_wei_bag_problem1():
    weight = [1, 3, 4]
    value = [15, 20, 30]
    bagweight = 4

    # 二維陣列
    dp = [[0] * (bagweight + 1) for _ in range(len(weight))]

    # 初始化
    for j in range(weight[0], bagweight + 1):
        dp[0][j] = value[0]

    # weight陣列的大小就是物品個數
    for i in range(1, len(weight)):  # 遍歷物品
        for j in range(bagweight + 1):  # 遍歷揹包容量
            if j < weight[i]:
                dp[i][j] = dp[i - 1][j]
            else:
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])

    print(dp[len(weight) - 1][bagweight])

test_2_wei_bag_problem1()

01揹包問題 一維dp

https://programmercarl.com/揹包理論基礎01揹包-2.html
影片講解:https://www.bilibili.com/video/BV1BU4y177kY

思考

在一維dp陣列中,dp[j]表示:容量為j的揹包,所背的物品價值可以最大為dp[j]。

思考

使用滾動陣列,先物品再揹包。揹包遍歷需要逆序,正序的話上一層的左側值就被覆蓋了,無法滾動。

def test_1_wei_bag_problem():
    weight = [1, 3, 4]
    value = [15, 20, 30]
    bagWeight = 4

    # 初始化
    dp = [0] * (bagWeight + 1)
    for i in range(len(weight)):  # 遍歷物品
        for j in range(bagWeight, weight[i] - 1, -1):  # 遍歷揹包容量
            dp[j] = max(dp[j], dp[j - weight[i]] + value[i])

    print(dp[bagWeight])

416. 分割等和子集

本題是 01揹包的應用類題目
https://programmercarl.com/0416.分割等和子集.html
影片講解:https://www.bilibili.com/video/BV1rt4y1N7jE

思考

暴力回溯太費事了。
轉換為01揹包問題。揹包容量為sum/2,物品重量為nums[i],價值也是nums[i]
dp[i] 揹包容量i是否可以裝滿

class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        if len(nums)==1:
            return False
        sum_ = sum(nums)
        if sum_ % 2 !=0:
            return False
        k = int(sum_ / 2)
        # dp[i] 揹包容量i是否可以裝滿
        dp = [False] * (k+1)
        dp[0] = True
        for num in nums:
            for i in range(k,0,-1):
                if i>=num:
                    dp[i] = dp[i] or dp[i-num]
        return dp[k]

相關文章