第九章 动态规划part03

2026.03.20 03.07 第三十九天

46 携带研究材料

二维背包问题,01背包

最基础的01背包问题,之前没有遇到过,看了很久才看懂,最重要的是推导出递推公式,还有边界值的初始化~

#include <iostream>
#include <math.h>
#include <vector>
using namespace std;

int main() {
    int n, bagWight;

    cin >> n >> bagWight;

    vector<int> weight(n, 0);
    vector<int> value(n, 0);

    for(int& i : weight) cin >> i;
    for(int& j : value) cin >> j;

    vector<vector<int>> dp(n, vector<int>(bagWight + 1, 0));

    for(int j = weight[0]; j < dp[0].size(); j++) {
        dp[0][j] = value[0];
    }

    for(int i = 1; i < dp.size(); i++) {
        for(int j = 0; j < dp[0].size(); 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[dp.size() - 1][dp[0].size() - 1];
}

46 携带研究材料

将二维数组压缩成了一维数组

对应的递推式也发生了变化

要注意当前还没有更新值的数组值就是i-1对应的数组值,又因为当前递推式只依赖i-1的状态,因此可以进行压缩

由于从前往后放会导致同一物品被放入多次,因此要从后往前放!!!

从递推关系式可知,一维数组所有值初始化为0即可

有一点理解难度,不过是从1到2,而不是零基础接触背包问题的从0到1;

for (int j = dp.size(); j >= weight[i]; j--)保证了j - weight[i]不会越界成为负数!

#include <iostream>
#include <math.h>
#include <vector>
using namespace std;

int main() {
    int n, bagWight;

    cin >> n >> bagWight;

    vector<int> weight(n, 0);
    vector<int> value(n, 0);

    for(int& i : weight) cin >> i;
    for(int& j : value) cin >> j;

    vector<int> dp(bagWight + 1, 0);

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

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

416 分割等和子集

非常巧妙,把分割子集问题转化为从nums中挑选一些数字,把nums中数字之和的一半装满,就说明能够分成和相等的两半,如此一来问题就和上一题完全一致了。

nums要先进行排序。

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum = 0;
        for(int& i : nums) sum += i;
        if(sum % 2) return false;
        sum /= 2;

        sort(nums.begin(), nums.end());
        vector<int> dp(sum + 1, 0);

        for(int i = 0; i < nums.size(); i++) {
            for(int j = dp.size() - 1; j >= nums[i]; j--) {
                dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
            }
        }
        if(dp[dp.size() - 1] == sum) return true;
        return false;
    }
};
posted @ 2026-03-20 21:18  遠くの君  阅读(0)  评论(0)    收藏  举报