494. 目标和(动态规划，01背包）

-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

class Solution {
public:

void backtrace(int sum,int S,vector<int>& nums,int pos) {
//符合条件直接添加返回
if(sum == S && pos == nums.size()){
result++;
return;
}
if(pos >= nums.size()) return;
//第i个数取+
sum += nums[pos];
backtrace(sum,S,nums,pos+1);
sum -= nums[pos];

//第i个数取-
sum -= nums[pos];
backtrace(sum,S,nums,pos+1);
sum += nums[pos];

}
int findTargetSumWays(vector<int>& nums, int S) {
backtrace(0,S,nums,0);
return result;
}
public:
int result = 0;
};

dp:要转化成dp

class Solution {
public:
//dp系列：01背包
//dp[i][j] = dp[i-1][j-nums[i]] + dp[i-1][j+nums[i]] 这种dp转移相对麻烦一些
//另一种想法：数组分为正负两部分.   例如1 3 5 为加 sum(P)  2 4为- sum(N)
//sum(P) + sum(N) = S
//sum(P) - sum(N) = sum(nums)
//sum(P) - sum(N) + sum(P) + sum(N) = S + sum(nums) ==> 2*sum(P) = s+sum(nums) ==> sum(P) = (S+sum(nums))/2
//典型的01背包，从nums中取 k个数使得和P 为(S+sum(nums))/2
int findTargetSumWays(vector<int>& nums, int S) {
int n = nums.size();
int sum = accumulate(nums.begin(),nums.end(),0);
long s = long(sum) + long(S);
if(s % 2 || sum < S) return 0;
vector<vector<int>> dp(n+1,vector<int>(s/2+1,0));
for(int i=1;i<=n;i++){
dp[i][0] = 1;
}
for(int j=1;j<=s/2;j++){
dp[0][j] = 0;
}
dp[0][0] = 1;
for(int i=1;i<=n;i++){　　　　　　　//j从0开始，否则 dp[1][0]对于某些情况失败，[0 0 1] 1中dp[1][0] = 2
for(int j=0;j<=s/2;j++){
if(j >= nums[i-1])
dp[i][j] = dp[i-1][j]+dp[i-1][j-nums[i-1]];
else
dp[i][j] = dp[i-1][j];
}
}
return dp[n][s/2];
}
};

posted on 2020-12-20 15:14  wsw_seu  阅读(90)  评论(0编辑  收藏  举报