EX494
You are given a list of non-negative integers, a1, a2, …, an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol.
Find out how many ways to assign symbols to make sum of integers equal to target S.
Example1:
Input: nums is [1, 1, 1, 1, 1], S is 3. Output: 5 Explanation: -1+1+1+1+1 = 3 +1-1+1+1+1 = 3 +1+1-1+1+1 = 3 +1+1+1-1+1 = 3 +1+1+1+1-1 = 3 There are 5 ways to assign symbols to make the sum of nums be target 3.
Solution:
这仍旧是一道对背包问题的变形,首先nums中的数分成两组,numP与numN,很容易得到:
sumP + sumN = sum
sumP - sumN = target
=====> sumP = (sum + target)/2
===================>整道题转换为了:求nums中取数,和为(sum + target)/2的不同组合方式的个数
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int len = nums.size(), sum = 0;
for (int i = 0; i < len; i++) {
sum += nums[i];
}
//target+sum为奇数时,显然可能的组合方式为0
if (S > sum || S < -sum || (S+sum)%2) {
return 0;
}
return canPartition(nums, (S+sum)/2);
}
//ex416的变形
int canPartition(vector<int>& nums, int target) {
int len = nums.size();
vector<int> dp(target+1, 0);
dp[0] = 1;
for (int i = 0; i < len; i++) {
for (int j = target; j >= nums[i]; j--) {
if (dp[j-nums[i]]) {
//求个数,所以累加
dp[j] += dp[j-nums[i]];
}
}
}
return dp[target];
}
};