class Solution {
public:
bool canPartition(vector<int>& nums) {
/*
两个子集元素和相等 -> 一个子集的和 = nums元素和 / 2;
dp[j] : 待定元素和为j的子集在nums数组中所能构成的最大元素和; 这里用最大元素和是为了让所有能选的元素都选上,
如果刚好等于sum / 2,则另一个子集的元素和肯定也是sum / 2
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]); 1: 对每个元素遍历,若满足j >= nums[i], 则更新最大元素和
*/
vector<int> dp(10001, 0); // target.max <= nums.length * nums[i] / 2 = 200 * 100 / 2= 10000
int sum = 0;
for(int i = 0; i < nums.size(); i ++){
sum += nums[i];
}
if(sum % 2 == 1) return false; // nums元素和为奇数,不可能分割为相等的2个子集
int target = sum / 2; //待定元素和为 sum / 2
for(int i = 0; i < nums.size(); i ++){
for(int j = target; j >= nums[i]; j --)
//j >= nums[i], 表示从待定元素和j = target到j = nums[i], 都更新一下最大元素和
//因为对于每一个dp[j],都是由上一轮dp[n](n <= j)计算得到的
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
//max(不加入nums[i]的最大元素和, 加入nums[i]的最大元素和)
}
if(dp[target] == target) return true;
else return false;
}
};