算法题打卡day42-背包问题 | 416. 分割等和子集

背包问题根据物品数量和取用方式的不同可以分成01背包(物品只有一个),完全背包(物品有无数个),多重背包(物品的个数不相同)和分组背包(按组打包,每组最多选一个)。重点掌握01背包和完全背包就好。有很多问题不会直接以背包的形式来考察,所以实际面对问题可能要经历一个先转换成背包问题的思考过程。下面先对这两个背包用五步法来进行分析。

01背包 

1. dp[i][j],表示背包容量为j时,从0到i-1的物品随便取,可以获得的最大价值;

2. 物品只有两种形态,拿或者不拿,所以dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i]);

3. i = 0,j =  0时,可选用物品为0,背包容量为0,dp[i][0] = 0, i = 1 时,当j >= weight[i]时dp[1][j] = value[1];

4. 遍历顺序先i再j或者先j再i都可以,因为dp[i][j]只与左上方的元素有关,不过从理解和底层存储的角度还是先i后j好点;

5. 举了一些例子发现没问题。

时间复杂度O(n^2),空间复杂度O(n),代码如下:

void test_2_wei_bag_problem1() {
    vector<int> weight = {1, 3, 4};
    vector<int> value = {15, 20, 30};
    int bagweight = 4;

    // 二维数组
    vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));

    // 初始化
    for (int j = weight[0]; j <= bagweight; j++) {
        dp[0][j] = value[0];
    }

    // weight数组的大小 就是物品个数
    for(int i = 1; i < weight.size(); i++) { // 遍历物品
        for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
            if (j < weight[i]) dp[i][j] = dp[i - 1][j];
            else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

        }
    }

    cout << dp[weight.size() - 1][bagweight] << endl;
}

int main() {
    test_2_wei_bag_problem1();
}

优化空间

压缩为一维矩阵:

dp[j] = max(dp[j], dp[j-weight[i]]+value[i]);

注意遍历顺序依然是双重遍历,但是对于背包容量j要从后往前遍历。

练习题

416. 分割等和子集 - 力扣(LeetCode)

状态:查看思路Debug后AC。

本题的难点有两处,首先是察觉到sum/2这一个点可以用来进行判断,跟着题目描述的思路进行下去路就走远了;其次就是如何用背包问题的框架对该问题进行适应。

在背包容量为sum/2的条件下,能不能找到组合让dp[sum/2] = sum/2。

代码如下:

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum = 0;
        int len = nums.size();
        for(int n : nums){
            sum += n;
        }
        if(sum % 2 == 1) return false;
        int target = sum / 2;
        vector<int> dp(10001, 0);
        for(int i = 0; i < len; ++i){
            for(int j = target; j >= nums[i]; --j){
                dp[j] = max(dp[j], dp[j-nums[i]]+nums[i]);
            }
        }
        if(dp[target] == target) return true;
        return false;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_40395888/article/details/132420258