本週選做的題目也是關於動態規劃的應用,Target Sum,題目要求如下:
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.
Example 1:
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.我們可以以另一種方式理解這道題目,將數分為正數(P)與負數(N),將P+N=target,所以我們有
sum(P) - sum(N) = target
sum(P) + sum(N) + sum(P) - sum(N) = target + sum(P) + sum(N)
2 * sum(P) = target + sum(nums)
因此就變成尋找nums的子集P,並且有sum(P) = (sum(nums) + target) / 2,sum(nums) + target必須是偶數,在程序中多加一句半段語句sum < s || (s + sum) % 2 ? 0 : subsetSum(nums, (s + sum) / 2);
以下為我參考相關動態規劃寫法並總結出來的程序
int subsetSum(vector<int>&
nums, int s)
{
int dp[s + 1] = { 0 };
dp[0] = 1;
for (int j = 0; j < nums.size(); j++)
{
int n = nums[j];
for (int i = s; i >= n; i--)
{
dp[i] += dp[i - n];
//cout << "dp " << i << ": " << dp[i]<<endl;
}
//cout << endl;
}
return dp[s];
}
int findTargetSumWays(vector<int>&
nums, int s)
{
int sum = accumulate(nums.begin(), nums.end(), 0);
return sum < s || (s + sum) % 2 ? 0 : subsetSum(nums, (s + sum) / 2);
}