leetcode 416.分割等和子集
第一次将背包问题模版抽象到实际问题,第一次做真的无从下手。
本题我们可以将i看作物品i,这个物品i的重量是num[i],这个物品的价值也是nums[i]。
思路:我们先将整个数组的和sum求出,再取其一半记为target,再用这个数组里面的元素去放入背包(每个元素只能使用一次),看看背包的最大容量为target时对应的价值是否为target,如果可以则代表数组里面元素可以组成target也就是sum/2。那么另一半没有使用过的元素也肯定可以组成sum/2,那么就说明数组是可以分成两个等和的子集的。
class Solution {
public:
bool canPartition(vector<int>& nums) {
//常规
if(nums.size()==1) return false;
int sum = accumulate(nums.begin(), nums.end(), 0);
//判断sum是否是一个偶数,如果不是偶数那么肯定不能将这个数组分成两个相同的子集
if(sum%2==1) return false;
int target=sum/2;
vector<int> dp(target+1,0);//dp数组初始化
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]);//这里nums[i]既是物品i的重量也是物品i的价值
}
}
if(dp[target]==target) return true;//判断容量为target的背包是否能正好装满
return false;
}
};