【Day42】代码随想录之动态规划0-1背包_416. 分割等和子集

这篇具有很好参考价值的文章主要介绍了【Day42】代码随想录之动态规划0-1背包_416. 分割等和子集。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

动态规划理论基础

动规五部曲:
  1. 确定dp数组 下标及dp[i] 的含义。
  2. 递推公式:比如斐波那契数列 dp[i] = dp[i-1] + dp[i-2]。
  3. 初始化dp数组。
  4. 确定遍历顺序:从前到后or其他。
  5. 推导dp数组。
出现结果不正确:
  1. 打印dp日志和自己想的一样:递推公式、初始化或者遍历顺序出错。
  2. 打印dp日志和自己想的不一样:代码实现细节出现问题。

416. 分割等和子集

参考文档:代码随想录

题目:

给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200

  • 示例 1:
    输入: [1, 5, 11, 5]
    输出: true
    解释: 数组可以分割成 [1, 5, 5] 和 [11].
  • 示例 2:
    输入: [1, 2, 3, 5]
    输出: false
    解释: 数组不能分割成两个元素和相等的子集.
  • 提示:
    1 <= nums.length <= 200
    1 <= nums[i] <= 100

分析:
【Day42】代码随想录之动态规划0-1背包_416. 分割等和子集,动态规划,算法,数据结构,leetcode,力扣,C++

dp五部曲:

  1. dp[j]含义:背包重量为i时候可以装最大价值数。
  2. 递推公式:dp[j] = max(dp[j], dp[j-nums[i]] + nums[i]);
  3. 初始化:vector<int> dp(total+1, 0); 不能影响dp[j]的更新,设为最小自然数0。
  4. 遍历顺序:双重for循环,先物品再背包,内层for循环的循环体 倒序 更新dp,适应滚动数组,不影响之前的更新,正序因为只有一个一维数组,所以会影响后面的更新。
  5. 打印:
    输入: [1, 5, 11, 5]
    dp更新:
    下标值:0,1,2,3,4,5,6,7,8,9,10,11
    初始化:0,0,0,0,0,0,0,0,0,0,0,0
    i = 0 :0,1,1,1,1,1,1,1,1,1,1,1
    i = 1 :0,1,1,1,1,5,6,6,6,6,6,6
    i = 2 :0,1,1,1,1,5,6,6,6,6,6,11
    i = 3 :0,1,1,1,1,5,6,6,6,6,10,11
    代码:
class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int total = 0;
        for(int i = 0; i < nums.size(); i++){
            total += nums[i];
        }
        if(total % 2) return false;
        total /= 2;// 背包的目标体积
        
        vector<int> dp(total+1, 0);

        for(int i = 0; i < nums.size(); i++){//物品个数0-nums.size()-1
            for(int j = total; j >= nums[i]; j--){//背包的体积0-total
                dp[j] = max(dp[j], dp[j-nums[i]]+nums[i]); //递推公式
            }
        }
        if(dp[total] == total) return true;
        return false;
    }
};

二维数组实现:

  1. dp[i][j]含义:从0-i的物品中任取到重量限制为j的背包得到的最大价值数。
  2. 递推公式:dp[i][j] = max(dp[i-1][j], dp[i-1][j-nums[i]] + nums[i]);
  3. 初始化:vector<vector<int>> dp(nums.size(), vector<int>(total+1, 0)); 第一列表示背包的重量为0时的价值为0,第一行表示在物品0存在的情况下背包不同重量的价值,满足条件的初始化为物品0的价值,其他元素都需要之后从上和左上的二维数组元素值计算得出,所以初始化值任意。
  4. 遍历顺序:双重for循环,对于二维数组,先物品再背包或者先背包再物品,在当前额日伪数组求最大价值的时候上和左上元素都是存在的,所以遍历顺序任意。

先物品再背包

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int total = 0;
        for(int i = 0; i < nums.size(); i++){
            total += nums[i];
        }
        if(total % 2) return false;
        total /= 2;// 背包的目标体积
        
        //二维数组
        vector<vector<int>> dp(nums.size(), vector<int>(total+1, 0));

        for(int i = total; i >= nums[0]; i--) dp[0][i] = nums[0];

        for(int i = 1; i < nums.size(); i++){//先物品
            for(int j = 1; j <= total; j++){//再背包
                if(j < nums[i]) dp[i][j] = dp[i-1][j];
                else dp[i][j] = max(dp[i-1][j], dp[i-1][j-nums[i]]+nums[i]);
            }
        }

        if(dp[nums.size()-1][total] == total) return true;
        return false;
    }
};

先背包再物品文章来源地址https://www.toymoban.com/news/detail-828766.html

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int total = 0;
        for(int i = 0; i < nums.size(); i++){
            total += nums[i];
        }
        if(total % 2) return false;
        total /= 2;// 背包的目标体积
        
        //二维数组
        vector<vector<int>> dp(nums.size(), vector<int>(total+1, 0));

        for(int i = total; i >= nums[0]; i--) dp[0][i] = nums[0];

        for(int j = 1; j <= total; j++){//先背包
            for(int i = 1; i < nums.size(); i++){//再物品
                if(j < nums[i]) dp[i][j] = dp[i-1][j];
                else dp[i][j] = max(dp[i-1][j], dp[i-1][j-nums[i]]+nums[i]);
            }
        }

        if(dp[nums.size()-1][total] == total) return true;
        return false;
    }
};

到了这里,关于【Day42】代码随想录之动态规划0-1背包_416. 分割等和子集的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【Day43】代码随想录之动态规划0-1背包_1049. 最后一块石头的重量 II_494. 目标和_ 474.一和零

    动态规划理论基础 动规五部曲: 确定dp数组 下标及dp[i] 的含义。 递推公式:比如斐波那契数列 dp[i] = dp[i-1] + dp[i-2]。 初始化dp数组。 确定遍历顺序:从前到后or其他。 打印。 出现结果不正确: 打印dp日志和自己想的一样:递推公式、初始化或者遍历顺序出错。 打印dp日志和

    2024年02月22日
    浏览(14)
  • 动态规划01背包问题-代码随想录-刷题笔记

    动态规划01背包问题-代码随想录-刷题笔记

    有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。 每件物品只能用一次 ,求解将哪些物品装入背包里物品价值总和最大。 二维dp数组01背包 确定dp数组以及下标的含义 是使用二维数组,即 dp[i][j] 表示从下标为[0-i]的物品里任意取,

    2024年02月07日
    浏览(35)
  • 二刷代码随想录——动态规划day40

    一个本硕双非的小菜鸡,备战24年秋招,计划二刷完卡子哥的刷题计划,加油! 二刷决定精刷了,于是参加了卡子哥的刷题班,训练营为期60天,我一定能坚持下去,迎来两个月后的脱变的,加油! 推荐一手卡子哥的刷题网站,感谢卡子哥。代码随想录 终于来到了守关boss。

    2024年03月11日
    浏览(36)
  • 代码随想录Day41:动态规划Part3

    代码随想录Day41:动态规划Part3

    讲解前: 毫无头绪 讲解后: 这道题的动态思路一开始很不容易想出来,虽然dp数组的定义如果知道是动态规划的话估摸着可以想出来那就是很straight forward dp定义:一维数组dp[i], i 代表整数的值,dp[i] 代表将整数 i 拆分的话可以获得的最大乘积 然后呢就是定义递归推导式了,

    2024年04月27日
    浏览(13)
  • 代码随想录第44天|动态规划:完全背包理论基础 518.零钱兑换II 377. 组合总和 Ⅳ

    代码随想录第44天|动态规划:完全背包理论基础 518.零钱兑换II 377. 组合总和 Ⅳ

    代码随想录 (programmercarl.com) 动态规划之完全背包,装满背包有多少种方法?组合与排列有讲究!| LeetCode:518.零钱兑换II_哔哩哔哩_bilibili 完全背包和01背包问题唯一不同的地方就是,每种物品有无限件 。 完全背包中的物品可以添加多次,所以要从小到大遍历: 518. 零钱兑换

    2024年04月25日
    浏览(13)
  • 代码随想录 day38 第九章 动态规划part01

    ●  理论基础 ●  509. 斐波那契数 ●  70. 爬楼梯 ●  746. 使用最小花费爬楼梯 理论基础 解决动态规划必须要想清楚的点 dp数组以及下标的含义 递推公式 dp数组如何初始化 遍历顺序 打印数组 检查结果 关联 leetcode 509. 斐波那契数 思路 动规五部曲 dp数组以及下标的含义

    2024年04月17日
    浏览(14)
  • 【代码随想录】Day 49 动态规划10 (买卖股票Ⅰ、Ⅱ)

    【代码随想录】Day 49 动态规划10 (买卖股票Ⅰ、Ⅱ)

    https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/ dp[i]表示在第i天时,卖/不卖股票能获得的最大利润: 1、卖股票:dp[i] = prices[i] -minPrice(i天以前的最低价格) 2、不卖股票:dp[i] = dp[i-1](因为不卖股票,所以状态和前一天保持一致) ∴dp[i] = max(dp[i-1], prices[i] - minPrice); https

    2024年02月09日
    浏览(5)
  • 【Day52】代码随想录之动态规划_打家劫舍

    动态规划理论基础 动规五部曲: 确定dp数组 下标及dp[i] 的含义。 递推公式:比如斐波那契数列 dp[i] = dp[i-1] + dp[i-2]。 初始化dp数组。 确定遍历顺序:从前到后or其他。 打印。 出现结果不正确: 打印dp日志和自己想的一样:递推公式、初始化或者遍历顺序出错。 打印dp日志和

    2024年02月22日
    浏览(12)
  • 【随想录学习】——第十章 动态规划(0-1背包+完全背包)

    【随想录学习】——第十章 动态规划(0-1背包+完全背包)

    动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。 所以动态规划中每一个状态一定是由上一个状态推导出来的, 这一点就区分于贪心 ,贪心没有状态推导,而是从局部直接选最优的, dp数组表示斐波那契数列,dp[i]表示

    2024年01月19日
    浏览(8)
  • 代码随想录 day44 完全背包

    class Solution { public:     int change(int amount, vectorint coins) {         vector int dp(amount+1,0);         dp[0]=1;         for(int i=0;icoins.size();i++){             for(int j=coins[i];j=amount;j++){                 dp[j]+=dp[j-coins[i]];             }         }  

    2024年02月15日
    浏览(10)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包