背包问题

#include <iostream>
#include <vector>
using namespace std;
class BackPack{
public:
/* 背包1:
 * 给定N个物品,重量分别为正整数
 * 一个背包的最大承重为整数M
 * 最多能带走多重的物品
 * */
    static int dpBackPack1(const vector<int> &arr, const int &weight){
        if(arr.empty()) return -1;
        vector<vector<bool>> dp(arr.size());
        for(auto &it:dp){
            it.resize(weight+1);
        }
        int maxWeight = 0;
        for(int i = 0; i < arr.size(); ++i){
            for(int w = 0; w < dp[i].size(); ++w){
                //dp[i][w]表示能否用前i个物品拼成重量w
                if(w == 0 || w == arr[i]){
                    dp[i][w] = true;
                    maxWeight = max(maxWeight, w);
                    continue;
                }
                dp[i][w] = false;
                if(i > 0){
                    dp[i][w] = dp[i-1][w] || dp[i][w] ;
                    if(w >= arr[i]){
                        dp[i][w] = dp[i-1][w - arr[i]] || dp[i][w];
                    }
                }
                maxWeight = dp[i][w] ? max(maxWeight, w) : maxWeight;
            }
        }
        return maxWeight;
    }
/*有 n 个物品和一个大小为 m 的背包.
 * 给定数组 A 表示每个物品的大小和数组 V 表示每个物品的价值.
 * 问最多能装入背包的总价值是多大?
 * 一个物品只能用一次
 * */
    static int dpBackPack2(const vector<int> &arr,
                           const vector<int> &value,
                           const int &target){
        if(arr.empty()) return -1;
        int n = (int)arr.size();
        vector<vector<int>> dp(n);
        for(auto &it:dp){
            it.resize(target + 1);
        }
        int maxVal = -1;
        for (int i = 0; i < dp.size(); ++i) {
            for (int j = 0; j < dp[i].size(); ++j) {
                //dp[i][j]表示用前i个物品拼出重量j的最大价值
                if(j == 0){
                    dp[i][j] = 0;
                    continue;
                }
                dp[i][j] = -1;
                if(i > 0){
                    dp[i][j] = max(dp[i][j], dp[i-1][j]);
                    if(j >= arr[i] && dp[i-1][j-arr[i]] != -1){
                        dp[i][j] = max(dp[i][j], dp[i-1][j-arr[i]] + value[i]);
                    }
                }
                maxVal = max(maxVal, dp[i][j]);
            }
        }
        return maxVal;
    }

    static int dpBackPack3(const vector<int> &arr,
                           const vector<int> &value,
                           const int &target){
        if(arr.empty() || value.empty()) return 0;
        int n = (int)arr.size();
        vector<vector<int>> dp(n);
        for(auto &it:dp){
            it.resize(target + 1);
        }
        int maxVal = -1;

        for (int i = 0; i < dp.size(); ++i) {
            for (int j = 0; j < dp[i].size(); ++j) {
                //dp[i][j]表示用前i个物品拼出重量j的最大价值
                if(j == 0){
                    dp[i][j] = 0;
                    continue;
                }
                dp[i][j] = -1;
                if(i > 0){
                    dp[i][j] = max(dp[i][j], dp[i-1][j]);
                }
                if(j >= arr[i] && dp[i][j-arr[i]] != -1){
                    dp[i][j] = max(dp[i][j], dp[i][j-arr[i]] + value[i]);
                }
                maxVal = max(maxVal, dp[i][j]);
            }
        }
        return maxVal;
    }
/* 背包5:
* 给定N个物品,重量分别为正整数
* 一个正整数Target
* 问有多少种方法可以拼出Target
* 每个只能用1次
* */
    static int dpBackPack5(const vector<int> &arr, const int &target){
        if(arr.empty()) return -1;
        int n = (int)arr.size();
        vector<vector<int>> dp(n + 1);
        for(auto &it:dp){
            it.resize(target + 1);
        }
        dp[0][0] = 1;
        for (int i = 1; i < dp.size(); ++i) {
            for (int j = 0; j < dp[i].size(); ++j) {
                //dp[i][j]表示用前i个物品拼出j有多少种方法
                dp[i][j] = dp[i-1][j];
                if(j >= arr[i-1]){
                    dp[i][j] += dp[i-1][j-arr[i-1]];
                }
            }
        }
        return dp[n][target];
    }
/* 背包6:
* 给定N个物品,重量分别为正整数
* 一个正整数Target
* 问有多少种方法可以拼出Target
* 每个可以用多次
* */
    static int dpBackPack6(const vector<int> &arr, const int &target) {
        if (arr.empty()) return -1;
        int n = (int) arr.size();
        vector<int> dp(target+1);
        dp[0] = 1;
        for(int i = 0; i < n; ++i){
            for(int j = 0; j < dp.size(); ++j){
                if(j >= arr[i]){
                    dp[j] += dp[j - arr[i]];
                }
            }
        }
        return dp[target];
    }
};
int main() {
    vector<int > arr = {2, 3, 5, 7};
    int weight = 11;
    //10 2 3 5
    cout<<BackPack::dpBackPack1(arr, weight)<<endl;
    arr = {1, 2, 3, 3, 7};
    int target = 7;
    cout<<BackPack::dpBackPack5(arr, target)<<endl;
    arr = {2, 3, 6, 7};
    target = 7;
    cout<<BackPack::dpBackPack6(arr, target)<<endl;
    arr = {2, 3, 5, 7};
    target = 10;
    vector<int> value = {1, 5, 2, 4};
    cout<<BackPack::dpBackPack2(arr, value, target)<<endl;
    arr = {1};
    target = 10;
    value = {1};
    cout<<BackPack::dpBackPack3(arr, value, target)<<endl;
    return 0;
}
posted @   蘑菇王国大聪明  阅读(28)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示