要求:如题
思路:先算出一半和,然后01背包, 跟平方和分割有点像,但是平方和那个没有数字限制,这个有,变成背包问题放n件物品每个物品只能用一次,价值等于sum/2,dp表示i件能否等于j,一个个放,不会重复,且不会漏
class Solution {
public:
bool canPartition(vector<int>& nums) {
int n=nums.size();
int sum=0;
for(int i=0;i<n;++i)
sum+=nums[i];
if(sum&1)return false;
sum=sum/2;
int dp[n+1][sum+1];
dp[0][0]=true;
for(int i=1;i<=n;++i)
dp[i][0]=true;
for(int i=1;i<=sum;++i)
dp[0][i]=false;
for(int i=1;i<=n;++i){
for(int j=1;j<=sum;++j)
if(j>=nums[i-1])//放得下
dp[i][j]=dp[i-1][j]||dp[i-1][j-nums[i-1]];
else dp[i][j]=dp[i-1][j];//放不下
}
return dp[n][sum];
}
};
优化:
class Solution {
public:
bool canPartition(vector<int>& nums) {
int n=nums.size();
int sum=0;
for(int i=0;i<n;++i)
sum+=nums[i];
if(sum&1)return false;
sum=sum/2;
vector<bool> dp(sum+1);
dp[0]=true;
for(int i=1;i<=n;++i)
for(int j=sum;j>=1;--j)
if(j>=nums[i-1])
dp[j]=dp[j-nums[i-1]]||dp[j];
return dp[sum];
}
};