动态规划(01背包问题的拓展)

这篇博客主要探讨了01背包问题的拓展应用,包括分割等和子集、最后一块石头的重量 II 和目标和三个经典题目。通过将这些问题转化为01背包问题,利用动态规划的思路,给出了递推公式和解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

01背包问题

这个问题之前有讲到过,可以参考动态规划01背包问题
此次主要讲述01背包问题下的拓展出来的一些问题。

题目一、分割等和子集

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

注意:
每个数组中的元素不会超过 100
数组的大小不会超过 200

示例 1:

输入: [1, 5, 11, 5]

输出: true

解释: 数组可以分割成 [1, 5, 5][11].

示例 2:

输入: [1, 2, 3, 5]

输出: false

解释: 数组不能分割成两个元素和相等的子集.

这种题乍一眼看到感觉无从下手,其实不然。
思路
1.首先思考一下,既然要将它们分为相等的两份,那么他们的和必然是偶数,否则必定不会被分成相等的两份。
2.这个问题如何转换为01背包问题呢,其实很简单,首先确定什么是背包的容量,什么是物品的容量,什么又是物品的价值。
数组中的所有的数的和我们是可以求出来的,那么排除它是偶数后,它的一半也是能算出来的,也就是说,如果我用数组中这些数能得到总和的一半,那么就表示我一定有一种方法可以把它分为相等的两份。
假设数组所有数的和为偶数并记为sum,那么它的一半记为half_sum,那么它就是背包的容量。而整个数组既是物品的重量,也是物品的价值。
那么这道题就可以理解为,再容量为half_sum的大小下,我能装入的最大的物品价值是多少。
求出这个最优解后,只需要和half_sum比较是否相等即可。
递推公式
创建dp数组,用i表示物品数,j表示当前容量,dp[j]表示j容量下的最大总和。
初始化为0,因为只要当前总和为0,那么我总是可以获取到比0大的总和。
dp[j] = max(dp[j],dp[j - nums[i]] + nums[i])

class Solution {
   
public:
    bool canPartition(vector<int>& nums) {
   
        int sum = 0;
        //求和
        for(int i = 0;i<nums.size();i++)
        {
   
          sum+=nums[i];
        }
        //判断是否为奇数
        if(sum % 2 == 1)  return false;
        //获得总和的一半,也是背包的容量
        int half_sum = sum/2;
        vector<int
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值