代码随想录 动态规划Ⅳ

416. 分割等和子集

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

class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        # 如果数组之和为奇数,则一定无法划分出两个元素和相等的子集
        if sum(nums) % 2 != 0:
            return False

        target = sum(nums) // 2

        # dp[i]数组定义,容量为i的背包(子集)可以容纳的最大价值(元素和)
        dp = [0] * (target + 1)

        # 先遍历商品,再倒序遍历背包容量
        for num in nums:
            for j in range(target, num-1, -1):
                dp[j] = max(dp[j], dp[j-num] + num)
        
        return dp[-1] == target

1049. 最后一块石头的重量 II

有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。

每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:

  • 如果 x == y,那么两块石头都会被完全粉碎;
  • 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x

最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0

思路:先不看粉碎,先看聚合,如何石头可以聚合成为两块一摸一样的石头,那么粉碎后的质量就为0. 举个例子,两块重量为5的石头可以拆解为113和23两团石头的对碰。因此,可以将目前给的石头堆尽可能地还原成重量相等的两堆石头。参考上一题,这里堆的大小为总量的 二分之一,往里面塞石头,占用的空间和提供的价值都是石头本身的重量。如此一来,就可以转化为01背包问题。

class Solution:
    def lastStoneWeightII(self, stones: List[int]) -> int:

        total_sum = sum(stones)
        target = sum(stones) // 2

        # dp[i]数组定义,容量为i的背包(子集)可以容纳的最大价值(元素和)
        dp = [0] * (target + 1)

        # 先遍历商品,再倒序遍历背包容量
        for stone in stones:
            for j in range(target, stone-1, -1):
                dp[j] = max(dp[j], dp[j-stone] + stone)
        
        return total_sum  - 2*dp[-1]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值