目标和
这次做的时候递推公式搞错了捏。
经过一些列骚操作(详情见代码首部注释),我们成功将目的转化为:给i个物品,重量和价值一致,最大容量s1,求能恰好装满s1的方法数。本来我想直接用之前的方法,每处理一件商品就判断一下,看看是不是到达最大容量了。如果是,那就ans++。但是这个思路有个致命的问题,就是会重复计算,比如我1 2 3可以,然后当i=4的时候,我不要4,那此时的结果因为取最大值,所以还是1 2 3,还是算做一次。
但是如果递推公式用 dp[j] += dp[j - nums[i]];
就不一样了,注意初始化 dp[0]=1,否则根本累加不了。
AC:
//相当于就是分成两组,两组和之差是target,求这种组合的方法个数
//s1-s2=target s1+s2=sum --> s1=(sum+target)/2,也就是求当前背包装的值为s1的个数
int findTargetSumWays(vector<int>& nums, int target)
{
int sum=0;
for(auto it:nums) sum+=it;
if((sum+target)%2==1) return 0; //如果和为奇数,那一定凑不出来
int s1=(sum+target)/2;
vector<int>dp(s1+1,0); //dp[i][j] 表示的是遍历前i个,当容量为j时,能放的方法数量
dp[0]=1;
for(int i=0;i<nums.size();i++)
for(int j=s1;j>=nums[i];j--)
{
dp[j] += dp[j - nums[i]]; //当前总方案数=之前统计的方案数+新增的方案数(也就是不选当前物品的方案数)
}
return dp[s1];
}