494目标和

题目描述

给你一个整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 ‘+’ 或 ‘-‘ ,然后串联起所有整数,可以构造一个 表达式 :

例如,nums = [2, 1] ,可以在 2 之前添加 ‘+’ ,在 1 之前添加 ‘-‘ ,然后串联起来得到表达式 “+2-1” 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

示例 1:

输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 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
+1 + 1 + 1 + 1 - 1 = 3

示例 2:

输入:nums = [1], target = 1
输出:1

分析

假设所有数的和是 sum,含有加号的数的和为 x ,那么含有减号的数的和就是 sum-x ;且依据题意,有x-(sum-x)=target;所以 x=(target+sum)/2。问题变成了容量为 x 的01背包有多少种装载方法。递推公式=>dp[j]=dp[j-num[0]]+dp[j-nums[1]]+···+dp[j-nums[n-1]]。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
vector<int> nums(n,0);
for(int i=0;i<n;i++)
{
cin>>nums[i];
}
int target;
cin>>target;
int sum=0;
for(int i=0;i<n;i++)
{
sum+=nums[i];
}
if(abs(target)>sum || (target+sum)%2!=0) cout<<0<<endl;
else
{
int bag=(target+sum)/2;
vector<int> dp(bag+1,0);
dp[0]=1;
for(int i=0;i<n;i++)
{
for(int j=bag;j>=nums[i];j--)
{
dp[j]+=dp[j-nums[i]];
}
}
cout<<dp[bag]<<endl;
}
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!