494. 目标和

这个我觉得还比较好理解,比较标准的背包DP
然后放个链接一个妹子的01背包讲解,觉得很不错,防止自己啥时候忘了再看看

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int S) 
    {
        int sum=accumulate(nums.begin(),nums.end(),0);
        if(sum<S||sum+S&1) return 0;
        int row=nums.size();
        int p=sum+S>>1; //寻找能在背包放下p体积东西的方法总数
        vector<vector<int>> dp(row+1,vector<int>(p+1,0));   //dp[i][j]截止到数组第i-1位,当前背包放j体积的东西的方法数
        dp[0][0]=1; //第一行第一列i=0,j=0,表示背包不放东西的方法数,为1
        for(int i=1;i<row+1;++i)
        {
            for(int j=0;j<p+1;++j)
            {
                int cur_pack=nums[i-1]; //当前的东西
                if(cur_pack<=j) //能放下,放和不放的方法数加一起
                {
                    dp[i][j]=dp[i-1][j]+dp[i-1][j-cur_pack];
                }
                else    //放不下,只能不放
                {
                    dp[i][j]=dp[i-1][j];
                }
            }
        }
        // cout<<"dp:"<<endl;
        // for(int i=0;i<row+1;++i)
        // {
        //     for(int j=0;j<p+1;++j)
        //     {
        //         cout<<dp[i][j]<<" ";
        //     }cout<<endl;
        // }
        return dp.back().back();
    }
};

这个神仙解法太??了,我就不记了,面试不可能想得出来

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int S) 
    {
        int sum=0;
        for(int num:nums)
        {
            sum+=num;
        }
        if(sum<S or (sum+S)%2)
        {
            return 0;
        }
        int p=(sum+S)/2;
        vector<int> dp(p+1,0);
        dp[0]=1;    //这个是任何数都不选的
        for(int num:nums)
        {
            //每次只考虑当前num选或不选
            for(int i=p;i>=num;--i)//从后遍历是防止更改较小的dp[i]值后,遍历dp[j](j>i)时,重复计量情况
            {
                dp[i]+=dp[i-num];
            }
        }
        // for(int x:dp)
        // {
        //     cout<<x<<" ";
        // }
        return dp.back();
    }
};
posted @ 2019-10-29 14:18  NeoZy  阅读(185)  评论(0编辑  收藏  举报