【C++编程能力提升】

代码随想录训练营Day42 | Leetcode 416

  • 一、01背包问题
    • 1、背包问题分类:
    • 2、01背包问题——二维dp数组
    • 3、01背包问题——一维dp数组(滚动数组,即当前行数据覆盖上一行数据)
  • 二、416 分割等和子集

一、01背包问题

1、背包问题分类:

主要掌握:01背包和完全背包
第一,01背包:有n件物品和一个最大容量为w的背包,第i件物品的重量是weight[i],其价值是value[i],每件物品只能使用一次(要么使用要么不使用),求解使用哪些物品能使背包里总价值最大。
第二,完全背包:与01背包的区别在于,物品数量是无数个,一个背包里可放置多个相同物品。
【C++编程能力提升】_第1张图片

2、01背包问题——二维dp数组

第一,dp数组的定义:dp[i][j]表示从下标为(0,i)的物品里选择(可选可不选),放在容量为j的背包,最大的价值总和。
第二,递推公式:dp[i][j]=max(dp[i-1][j],dp[i-1][j-wight[i]]+value[i]),要么不选物品i,此时最大价值总和仍为dp[i-1][j](不选的原因是此时背包容量j不足以放置物品i:j 第三,dp数组的初始化:
第一列表示背包容量为j=0选择物品的情况,由于容量为0无法放置物品,因此最大价值总和一定是0;
第一行表示不同背包容量j放入物品0后的最大价值总和,若背包容量j小于物品0的重量,则无法放置,故最大价值总和为0,否则可以放置物品0,故最大价值总和为物品0的价值;
其他元素均可初始化为0,因为后续遍历时会依次覆盖(更新)值。
第四,遍历顺序,需要循环物品和背包容量,先循环物品或先循环背包都可以;循环物品时由于物品0已经初始化,因此从物品1开始遍历,背包容量则从0开始遍历直到最大容量。由于背包容量从0开始因此可能存在背包容量小于当前物品重量的情况,此时无法放置该物品,那么此时的最大价值总和需继承上一个未放置此物品的最大价值总和。
注意:由递推公式可知,当前元素的值依赖于上一行的正上方和斜上方(即top和top-left)的元素值。

3、01背包问题——一维dp数组(滚动数组,即当前行数据覆盖上一行数据)

第一,dp数组的定义:dp[i]表示容量为j的背包,其物品价值最大为dp[j];
第二,递推公式:dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);由二维推导一维
第三,dp数组的初始化:dp[0]=0表示背包容量为0的物品最大价值总和为0;其他位置的元素值由于需要取max,因此初始化为0;
第四,遍历顺序:依然需要遍历物品和背包容量,外循环遍历物品时从物品0开始,而不是从物品1开始,内循环遍历背包容量时必须是倒序遍历,即从最大容量从后往前遍历到当前物品的重量,因为当前位置的元素值依赖于上方位置和左上方(或者斜上方)元素值,必须保证更新当前位置元素值时这俩元素值是未更新的。

二、416 分割等和子集

题目链接:416 分割等和子集

核心:所有元素分成2个子集要求子集元素和为sum/2,即选择元素使其背包容量最大为sum/2,且每个元素只能选择一次,属于01背包问题。

    bool canPartition(vector<int>& nums) {
        //01背包问题,背包最大重量是sum/2
        int sum=0;
        for(int num:nums)
            sum+=num;
        if(sum%2==1)
            return false;   //和为奇数无法分成2个子集
        int target=sum/2;   //背包最大重量
        //dp数组:dp[j]表示子集加入元素j后,子集之和为dp[j]
        vector<int> dp(10001,0); //nums长度最大200,元素值最大100,总和不超过20000
        for(int i=0;i<nums.size();++i)
        {//外循环先遍历数组的元素值,从第一个到最后一个元素
            for(int j=target;j>=nums[i];--j)    //内循环再遍历背包重量,倒序
                dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);
        }//如果找到2个合适的子集,则dp数组最大背包重量的值恰好为背包最大重量(!!)
        if(dp[target]==target)
            return true;
        return false;
    }

你可能感兴趣的:(C++编程,c++,leetcode,动态规划)