代码随想录刷题60Day
前言
今天主要讨论背包问题中的01背包问题,这类问题的难点在于怎样对问题进行数学建模。一旦思考好问题的解决方式,剩下的步骤就比较简单了。
分割等和子集
本题可采用暴力回溯,但复杂度比较高,所以采取动态规划会更好。但难点在于怎样将该问题转化成能够采取动规策略的01背包问题。
bool canPartition(vector<int>& nums)
{
if (nums.size() == 1)return false;
int sum = 0;
int size = nums.size();
sort(nums.begin(), nums.end());
for (int i = 0; i < size; ++i)
sum += nums[i];
if (sum % 2)return false;
int target = sum / 2;
vector<int> dp(target + 1, 0);
for (int i = 0; i < size; ++i)
{
for (int j = target; j >= nums[i]; --j)
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
}
if (dp[target] == target)return true;
return false;
}
最后一块石头的重量
int lastStoneWeightII(vector<int>& stones)
{
int sum = 0;
const int size = stones.size();
for (int i = 0; i < size; ++i)
sum += stones[i];
int target = sum / 2;
vector<int> dp(target + 1, 0);
for (int i = 0; i < size; ++i)
{
for (int j = target; j >= stones[i]; --j)
dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);
}
return sum - 2 * dp[target];
}