代码随想录算法训练营第四十一天 | 背包问题(一维、二维)、416. 分割等和子集

01背包:n种物品,每种物品只有1个,有相应的重量和价值

最多只能装m的重量,最多价值为多少?

dp[i][j] : [0, i]物品任取放进容量为j的背包里

不放物品i:dp[i-1][j]

放物品i:dp[i-1][j-weight[i]] + value[i]

        dp[i-1][j-weight[i] - 不放物品i的时候(容量腾出i),所放的最大价值

        value[i] - 把i物品放进去,最终最大价值

递推公式:放i和不放i两种情况

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

初始化:i是物品,j是重量,初始化第一行和第一列

根据递推公式:

        dp[i-1][j] - 上方

        dp[i-1][j-weight[i]] + value[i] - 左上方

第一列:容量是0,初始化成0

第一行:根据物品0来进行初始化

其他位置:任意值

代码随想录算法训练营第四十一天 | 背包问题(一维、二维)、416. 分割等和子集_第1张图片

 遍历:

先背包再物品都可以

DP41 【模板】01背包

#include 
#include 
using namespace std;

int main() {
    int bageweight = 0; // 背包重量
    int size = 0; // 物品数量
    cin >> size >> bageweight;

    vector weight(size, 0);
    vector value(size, 0);
    for(int i=0; i>weight[i];
        cin>>value[i];
    }

    // 定义dp数组:表示 [0, i]物品任取,背包容量为j的最大价值
    vector> dp(size, vector(bageweight+1, 0));
    // 初始化:第一行
    for(int i=weight[0]; i<=bageweight; ++i) {
        dp[0][i] = value[0];
    }

    // 先遍历物品 再遍历背包
    for(int i=1; i

一维dp数组

滚动数组:更新一行一行;上一层数据进行拷贝

dp[j] :容量为j的背包,所背最大价值为dp[j]

递推公式:dp[j] = max(dp[j], dp[j-weight[i]]+value[i])

初始化:0

遍历顺序:

第一个遍历是物品(先行,一列一列遍历--拷贝)

第二个是背包(倒序)- 避免重复添加

#include 
#include 
using namespace std;

int main() {
    int bageweight = 0; // 背包重量
    int size = 0; // 物品数量
    cin >> size >> bageweight;

    vector weight(size, 0);
    vector value(size, 0);
    for(int i=0; i>weight[i];
        cin>>value[i];
    }

    vector dp(bageweight+1, 0);
    for(int i=0; i=weight[i]; --j) {
            dp[j] = max(dp[j], dp[j-weight[i]]+value[i]);
        }
    }

    cout<

复习:

#include 
#include 
using namespace std;

int main() {
    int bageweight = 0; // 背包重量
    int size = 0; // 物品数量
    cin >> size >> bageweight;

    vector weight(size, 0);
    vector value(size, 0);
    for(int i=0; i>weight[i];
        cin>>value[i];
    }

    // [0, i] 个物品 背包重量为j的情况下所能取到的最大价值
    vector> dp(size, vector(bageweight, 0));
    // 初始化
    // 第一行
    for(int j=weight[0]; j<=bageweight; ++j) {
        dp[0][j] = value[0];
    }
    for(int i=1; i
#include 
#include 
using namespace std;

int main() {
    int bageweight = 0; // 背包重量
    int size = 0; // 物品数量
    cin >> size >> bageweight;

    vector weight(size, 0);
    vector value(size, 0);
    for(int i=0; i>weight[i];
        cin>>value[i];
    }

    vector dp(bageweight+1, 0);

    for(int i=0; i=weight[i]; --j) {
            dp[j] = max(dp[j], dp[j-weight[i]]+value[i]);
        }
    }

    cout<

416. 分割等和子集

class Solution {
public:
    bool canPartition(vector& nums) {
        int sum = 0;
        for(int num:nums) {
            sum += num;
        }
        if(sum%2==1) {
            return false;
        }
        int target = sum/2;

        vector dp(10001, 0);
        for(int i=0; i=nums[i]; --j) {
                dp[j] = max(dp[j], dp[j-nums[i]]+nums[i]);
            }
        }
        if(dp[target]==target) return true;
        return false;
    }
};

你可能感兴趣的:(算法,数学建模)