代码随想录——动态规划13.分割等和子集

image

思路

难点

我只想到了:“找一个子集,每个数取或不取求其和,看是否和另一个子集的和相等 ”
但是实际上既然是两个子集相等,那么只要和等于 sum/2 即可了!
取或不取用01背包,但是不知道怎么用。

只有确定了如下四点,才能把01背包问题套到本题上来。

  1. 背包的体积为sum / 2
  2. 背包要放入的商品(集合里的元素)重量为 元素的数值,价值也为元素的数值
  3. 背包如果正好装满,说明找到了总和为 sum / 2 的子集。
  4. 背包中每一个元素是不可重复放入。

套用01背包时,要确定容量和价值分别取什么。

代码

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        // 找一个子集,每个数取或不取求其和,看是否和另一个子集的和相等 —————— 错!!既然是两个子集相等,那么只要和等于 sum/2 即可了!
        // 取或不取——想到01背包。背包的容量取 sum/2 即可。num[i]即为重量也为价值。
        int n = nums.size();
        int sum = 0;
        for(auto x : nums)sum+=x;
        if(sum % 2 !=0 )return false;

        vector<int> dp(sum/2+1,0); // dp[j]表示容量为j的背包,能装入的最大价值
        // 当dp[sum/2]==sum/2时说明背包装满了,即找到了一个子集
        for(int i=0;i<n;i++){
            for(int j=sum/2;j>=nums[i];j--){
                dp[j] = max(dp[j],dp[j-nums[i]] + nums[i]);
            }
        }
        if(dp[sum/2] == sum/2)return true;
        else return false;
    }
};
posted @ 2024-12-29 11:26  NeroMegumi  阅读(71)  评论(0)    收藏  举报