第零章:经典动态规划:子集背包问题

labuladong经典动态规划:子集背包问题


动态规划之背包汇总

第零章:动态规划解题套路框架
第一章:经典动态规划:0-1 背包问题
第零章:经典动态规划:子集背包问题
第零章:经典动态规划:完全背包问题


该背包问题相当于0-1背包问题的变体

416. 分割等和子集

给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

0-1背包问题:背包容量为m,物品有大小和价值两种属性,求背包最大能装多少价值的物品? 0-1背包问题变体(分割等和子集):背包容量为total/2, 每个物品的大小为 nums[i] 。对于前i个物品,是否有一种装法,能恰好装满背包?
dp[i][j] 表示对前i个物品,背包容量为j时,可以装的最大价值 dp[i][j] 表示对前i个物品,背包容量为j时,值为True/ False (能否装满)
  • dp数组行和列都分别增加1,第0列表示背包容量为0,第0行表示(虚拟)物品重量为0(这样做,方便初始化dp数组以及后续dp状态转移)
  • 由于加了虚拟的0行和0列, 物品i从 1 开始,而数组索引是从 0 开始的,所以第 i 个物品的重量应该是 nums[i-1]
class Solution(object):
    def canPartition(self, nums):
        total=sum(nums) # total为列表之和
        if total%2!=0:return False # 若无法被2整除,说明无法等和,直接返回False

        # 行和列都分别增加1,第0列表示背包容量为0,第0行表示(虚拟)物品重量为0
        # 这样做,方便初始化dp数组以及后续dp状态转移
        dp=[[False for _ in range(total/2 + 1)] for _ in range(len(nums)+1)]
        for i in range(len(nums)+1):# 和为0时,第一列为True
            dp[i][0]=True
        for i in range(1,len(nums)+1):
            for j in range(1,total/2 + 1):
                if j<nums[i-1]: # 若背包容量超过物品大小,装不下
                    dp[i][j] = dp[i - 1][j] # 继承之前的结果
                else: # 继承之前装下/装不下的结果(只要之前有True,dp[i][j]就为True)
                    dp[i][j]= dp[i-1][j] | dp[i-1][j-nums[i-1]]
        return dp[-1][-1]

   转载规则


《第零章:经典动态规划:子集背包问题》 M 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
第零章:经典动态规划:完全背包问题 第零章:经典动态规划:完全背包问题
labuladong经典动态规划:完全背包问题 动态规划之背包汇总 第零章:动态规划解题套路框架第一章:经典动态规划:0-1 背包问题第零章:经典动态规划:子集背包问题第零章:经典动态规划:完全背包问题 0-1背包 完全背包
2020-07-27
下一篇 
第一章:经典动态规划:0-1 背包问题 第一章:经典动态规划:0-1 背包问题
labuladong 经典动态规划:0-1 背包问题 动态规划之背包汇总 第零章:动态规划解题套路框架第一章:经典动态规划:0-1 背包问题第零章:经典动态规划:子集背包问题第零章:经典动态规划:完全背包问题 题目地址 有 n 个物品
2020-07-27
  目录