给你一个整数数组 nums 和一个整数 target 。
向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :
例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。 返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。
先转化为求正数部分恰好等于目标值的方案总数问题, 即恰好装满背包的方案数.
定义边界条件:
$$ d p [ 0 ] [ j ] = \left\{ \begin{array} { l l } 1 , & j = 0 \\ 0 , & j \geq 1 \end{array} \right. $$
当没有元素时, 只有总重量为0的解法, 因此只有 dp[0][0]=1
$\begin{array} { l } \text { 如果 } j < n u m , \text { 则不能选 } n u m , \text { 此时有 } d p [ i ] [ j ] = d p [ i - 1 ] [ j ] ; \\ \text { 如果 } j \geq n u m , \text { 则如果不选 } n u m , \quad \text { 方案数是 } d p [ i - 1 ] [ j ] , \text { 如果选 } n u m , \text { 方案数是 } d p [ i - 1 ] [ j - n u m ] , \\ \text { 此时有 } d p [ i ] [ j ] = d p [ i - 1 ] [ j ] + d p [ i - 1 ] [ j - n u m ] _ { 0 } \end{array}$
所以状态转移方程为
$$ d p [ i ] [ j ] = \left\{ \begin{array} { l l } d p [ i - 1 ] [ j ] , & j < \text { nums } [ i ] \\ d p [ i - 1 ] [ j ] + d p [ i - 1 ] [ j - \text { nums } [ i ] ] , & j \geq \text { nums } [ i ] \end{array} \right. $$
题解:
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
int sum=0;
for (int &a:nums) sum+=a;
if ((sum+target)%2) return 0;
int p_sum = (sum+target)/2;
if (p_sum<0) return 0;
vector<vector<int>> dp(nums.size()+1, vector<int>(p_sum+1, 0));
// 总重为0, 则方案数为1
dp[0][0] = 1;
for (int i=1; i<=nums.size(); i++){
for (int j=p_sum; j>=0; 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.at(nums.size()).at(p_sum);
}
};