动态规划-01背包问题-分割等和子集问题(能不能装满背包)

leetcode 416.分割等和子集
第一次将背包问题模版抽象到实际问题,第一次做真的无从下手。
本题我们可以将i看作物品i,这个物品i的重量是num[i],这个物品的价值也是nums[i]。
思路:我们先将整个数组的和sum求出,再取其一半记为target,再用这个数组里面的元素去放入背包(每个元素只能使用一次),看看背包的最大容量为target时对应的价值是否为target,如果可以则代表数组里面元素可以组成target也就是sum/2。那么另一半没有使用过的元素也肯定可以组成sum/2,那么就说明数组是可以分成两个等和的子集的。

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        //常规
        if(nums.size()==1) return false;
        int sum = accumulate(nums.begin(), nums.end(), 0);
        //判断sum是否是一个偶数,如果不是偶数那么肯定不能将这个数组分成两个相同的子集
        if(sum%2==1) return false;
        int target=sum/2;


        vector<int> dp(target+1,0);//dp数组初始化
        for(int i=0;i<nums.size();i++){
            for(int j=target;j>=nums[i];j--){//从后往前遍历,原因去看代码随想录
                dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);//这里nums[i]既是物品i的重量也是物品i的价值
            }
        }
        if(dp[target]==target) return true;//判断容量为target的背包是否能正好装满
        return false;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值