自学动态规划——目标和

目标和

494. 目标和 - 力扣(LeetCode)

这次做的时候递推公式搞错了捏。

经过一些列骚操作(详情见代码首部注释),我们成功将目的转化为:给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];
}

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值