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();
}
};
进击的小🐴农