0-1背包相关题目

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        // 动态规划解法,将nums求和,背包容量是一半,物品就是nums里的所有元素看能不能刚好凑出来
        int sum = 0;
        for (int num : nums)
            sum += num;
        if (sum % 2 != 0)
            return false; // 如果没法分成两半,不可能分割
        sum = sum / 2; // 和分一半,背包容量为一半
        int n = nums.size();
        vector<vector<bool>> dp(n+1, vector<bool>(sum+1, false));
        // dp[i][j]:背包容量为j,前i个物品是否能够恰好装满,装满为true
        for (int i = 0; i < n; i++)
            dp[i][0] = true; // 相当于背包被装满了
        for (int i = 1; i < n+1; i++) {
            for (int j = 1; j < sum+1; j++) {
                if (j - nums[i-1] < 0) // 此时背包容量为j,判断是否能装下第i个元素,nums数组中,第i个元素的下标是i-1,
                    dp[i][j] = dp[i-1][j]; // 如果装不下,继承前一个状态的结果,也就是不加入第i个元素
                else { // 装入或者不装入背包两种选择,看两种有没有满足条件的
                    dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]];
                }
            }
        }
        return dp[n][sum];
    }
};
// 以下为第二种一维数组解法
class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum = 0;
        for (int num : nums)
            sum += num;
        if (sum % 2 != 0)
            return false;
        int n = nums.size();
        sum = sum / 2;
        // 问题转化为,nums当中的数,能否正好装满sum容量的背包 0-1背包问题
        vector<bool> dp(sum+1, false);
        // dp[j]:容量为j时是否能刚好被填满
        dp[0] = true; // 容量为0时更正好被填满
        for (int i = 1; i <= n; i++) {
            for (int j = sum; j >= 1; j--) {
                if (j - nums[i-1] >= 0)
                    dp[j] = dp[j] || dp[j-nums[i-1]];
            }
        }
        return dp[sum];
    }
};

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        // 动态规划 分成两堆重量相等的石头
        int sum = 0;
        for (int stone : stones)
            sum += stone;
        int target = sum / 2; // 向下取整,以下求能装满target的最大重量
        int n = stones.size();
        vector<int> dp(target+1, 0);
        // dp[j]:容量为j能装下的最大重量
        dp[0] = 0;
        for (int i = 1; i <= n; i++)  {
            for (int j = target; j >= 1; j--) {
                if (j - stones[i-1] >= 0)
                    dp[j] = max(dp[j], dp[j-stones[i-1]] + stones[i-1]);
            }
        }
        return sum - dp[target] - dp[target];
    }
};

posted @ 2021-02-03 20:24  不妨不妨,来日方长  阅读(60)  评论(0编辑  收藏  举报