题目:416. 分割等和子集
思路
动态规划,01背包问题;
难点在于转化为01背包问题,所以这是一道应用题;
普通的01背包:
f[i][j]
:前i
个物品放进容量为j
的背包里,所能装的最大价值;- 状态转移方程:
f[i][j] = max(f[i-1][j], f[i-1][j - weights[i]] + values[i])
;
本题的01背包:
f[i][j]
:前i个数字放进容量为j的背包里,所能装的最大价值;- 状态转移方程:
f[i][j] = max(f[i-1][j], f[i-1][j - nums[i]] + nums[i])
; weights[i] = nums[i]
,values[i] = nums[i]
,背包容积为所有数字的和(因为即使所有数字都塞进去加起来也就这么多);
代码
// weights[i] = nums[i], values[i] = nums[i];
// f[i][j] : i 个数字装进容量为j的背包里,所能装的最大价值
// f[i][j] = max(f[i-1][j], f[i-1][j-weights[i]] + values[i]);
//
class Solution {
public:
bool canPartition(vector<int>& nums) {
int i, j;
int sum = 0;
for(i = 0; i < nums.size(); i++)
{
sum += nums[i];
}
if(sum % 2 == 1)
{
return false;
}
cout << "sum : " << sum << endl;
vector<vector<int>> f(nums.size(), vector<int>(sum+1, 0));
// 初始化
for(j = nums[0]; j <= sum; j++)
{
f[0][j] = nums[0];
}
for(i = 1; i < nums.size(); i++)
{
for(j = 1; j <= sum; j++)
{
if(j < nums[i])
{
f[i][j] = f[i-1][j];
}
else
{
f[i][j] = max(f[i-1][j], f[i-1][j - nums[i]] + nums[i]);
}
}
}
if(f[nums.size()-1][sum/2] == sum/2)
{
return true;
}
else
{
return false;
}
}
};