目标和问题---动态规划+背包问题+数学

思路

数学推导:

将数组随机分为两部分,第一部分和为left,第二部分和为right,数组总和为sum,目标和为target
可以得到:

	left+right=sum
	left-right=target

可以推出:
left=(sum+target)/2 或者 right=(sum-target)/2

以上两种选择都可以通过,我选择第二种 diff=sum-target

  • 如果diff<0显然不成立,因为所有元素都是非负数
  • 如果diff为奇数也不成立,应为所有元素都为整数,相加不可能有小数

综上所述,可以将问题转化为背包问题,将容量为left的背包装满有多少种方式。

背包问题:装满背包有多少种方式。

dp[i][j]的含义:有i件物品,背包容量为j时,装满背包最多有多少种;

  • 当j<num[i-1]时,只有一种情况,不装第i件物品,即有i-1件物品,容量为j时,装满有多少种情况,dp[i][j]=dp[i-1][j].
  • 当j>=nums[i-1]时,有两种情况,装和不装第i件物品,总方式有这两种情况相加得到,d[i][j]=d[i-1][j]+dp[i-1][j-nums[i-1]]
  • 注意:nums数组下表从0开始,循环从1开始。

链接:https://leetcode.cn/problems/target-sum/solutions/2837852/dong-tai-gui-hua-bei-bao-wen-ti-shu-xue-n5pka/

代码

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int n = nums.size();
        int sum = 0;
        for (int a : nums)sum += a;//所有数的和
        //如果为奇数,不存在目标和为target的情况
        if (sum - target<0||(sum + target) % 2 == 1)return 0;
        //dp[i][j]的含义:当有i个数,目标和为j时,装满背包的方式最多有多少种
        int dp[1010][1010] = { 0 };
        int m = (sum - target) / 2;
        //初始化dp
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 0; j <= m; j++)
            {
                if (nums[i-1] > j)
                {
                    dp[i][j] = dp[i - 1][j];
                 }
                else {
                    dp[i][j] = dp[i - 1][j - nums[i - 1]] + dp[i - 1][j];
                }
            }
        }
        return dp[n][m];
    }
};
posted @   wsxspace  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示