Bootstrap

动态规划之01背包和完全背包问题(力扣C++题解)

理论内容都在代码随想录了,这里我主要是自己写题解回顾,强烈推荐

代码随想录代码随想录PDF,代码随想录百度网盘,代码随想录知识星球,代码随想录八股文PDF,代码随想录刷题路线,代码随想录知识星球八股文https://www.programmercarl.com/%E8%83%8C%E5%8C%85%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8001%E8%83%8C%E5%8C%85-1.html

 

目录

模板一:二维数组版本

 模板二:一维数组版本(滚动数组)

1:分割等和子集(01背包)

2:最后一块石头的重量 II(01背包)

3:目标和(组合问题)

 4:一和零

完全背包:

5:零钱兑换||(组合问题)

6:零钱兑换||||(排列总和)


模板一:二维数组版本

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();
}

问题:

(1)初始化问题:不能随意的凭感觉的初始化为0,或初始化为1,要根据实际情况

当这个点是初始点时,将数据带入,并检查,因为这个点时所有点的基石

当这个点不为初始点时,一般初始化为0(防止覆盖后面递推得出的数据)

比如在这个模板中:将第一行全部初始化为value[0]

意义为:当背包容量>=1时,如果只放第一件物品,那么背包所得到的最大价值就是value[0]

 (2)for循环遍历顺序问题:

一般我们都是先正序遍历物品的重量,再正序遍历背包容量,但实际上,在二维数组中,这个顺序完全可以颠倒,即先正序遍历背包容量,再正序遍历物品的重量;

因为它们之间互相不会覆盖,所以不受影响,但是下面的一维数组就要考虑了

(3)递推公式问题:01背包模板递推公式:

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

含义:dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少

返回即返回dp[weight.size()-1][bagweight],也就是递推的最后一步

当不放入物品时:背包容量没有损失,最大价值等于上一个的价值(没有拿,价值不变)

当放入物品时:背包容量=背包容量-物品的重量,最大价值等于上一个的价值+新增物品的价值

 模板二:一维数组版本(滚动数组)

#include<vector>
#include <stack>
#include<queue>
#include<iostream>
using namespace std;
void test()
{
    vector<int> weight = { 1, 3, 4 };
    vector<int> value = { 15, 20, 30 };
    int bagweight = 4;
    //核心是:物品重量作为底,将背包的最大容量作为天花板,将天花板依次--,直到正好等于底
    //依次统计天花板降低时,dp[j]的最大价值
    //之后再重新换一个底,重复上述步骤
    vector<int> dp(bagweight + 1, 0);
    for (int i = 0; i < weight.size(); i++)//物品重量
    {
        for (int j = bagweight; j >= 
;