思路
难点
我只想到了:“找一个子集,每个数取或不取求其和,看是否和另一个子集的和相等 ”
但是实际上既然是两个子集相等,那么只要和等于 sum/2 即可了!
取或不取用01背包,但是不知道怎么用。
只有确定了如下四点,才能把01背包问题套到本题上来。
- 背包的体积为sum / 2
- 背包要放入的商品(集合里的元素)重量为 元素的数值,价值也为元素的数值
- 背包如果正好装满,说明找到了总和为 sum / 2 的子集。
- 背包中每一个元素是不可重复放入。
套用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;}
};