• leetcode刷题(132)——完全背包问题思路理解


    完全背包问题描述

    有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品都有无限个(也就是可以放入背包多次),求解将哪些物品装入背包里物品价值总和最大。

    完全背包和01背包问题唯一不同的地方就是,每种物品有无限件。

    同样leetcode上没有纯完全背包问题,都是需要完全背包的各种应用,需要转化成完全背包问题,所以这里还是以纯完全背包问题进行讲解理论和原理。

    版本1:这是朴素版本的,时间复杂度O(nm^2)

    #include
    using namespace std;
    
    const int N = 1010;
    
    int n, m;
    int dp[N][N], v[N], w[N];
    
    int main(){
        cin >> n >> m;
        for(int i = 1; i <= n; i ++ )
            cin >> v[i] >> w[i];
    
        for(int i = 1; i <= n; i ++ )
            for(int j = 0; j <= m; j ++ )
                for(int k = 0; k * v[i] <= j; k ++ )
                    dp[i][j] = max(dp[i][j], dp[i - 1][j - k * v[i]] + k * w[i]);
        cout << dp[n][m] << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    版本2:这个就是把上面版本的第三重循环优化掉,优化的原理就是:
    dp[i][j - v] = max(dp[i - 1][j - v], dp[i - 1][j - 2 * v] + w, dp[i - 1][j - 3 * v] + 2 * w, …);
    而我们需要的dp[i][j]的状态表示是:
    dp[i][j]= max(dp[i - 1][j], dp[i - 1][j - v] + w, dp[i - 1][j - 2 * v] + 2 * w, dp[i - 1][j - 3 * v] + 3 * w);
    将每一项一一比对,我们可以得到下列状态表示:
    dp[i][j] = max(dp[i - 1][j], dp[i][j - v] +w);

    #include
    using namespace std;
    
    const int N = 1010;
    
    int n, m;
    int dp[N][N], v[N], w[N];
    
    int main(){
        cin >> n >> m;
        for(int i = 1; i <= n; i ++ ){
            int v, w;
            cin >> v >> w;
            for(int j = 0; j <= m; j ++ ){
                dp[i][j] = dp[i - 1][j];
                if(j >= v)
                    dp[i][j] = max(dp[i][j], dp[i][j - v] + w);
            }
        }
        cout << dp[n][m] << endl;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    版本3:对代码进行等价变形。对照01背包的代码,就是将第二个循环从小到大进行枚举即可。

    #include
    using namespace std;
    
    const int N = 1010;
    
    int n, m;
    int dp[N];
    
    int main(){
        cin >> n >> m;
        for(int i = 1; i <= n; i ++ ){
            int v, w;
            cin >> v >> w;
            for(int j = v; j <= m; j ++ ){
                    dp[j] = max(dp[j], dp[j - v] + w);
            }
        }
        cout << dp[m] << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    HTB-Armageddon
    2023 最新 PDF.js 在 Vue3 中的使用(长期更新)
    Jmeter 分布式压测,你的系统能否承受高负载?
    CSS 效果 圆形里一个文字居中
    【版本控制】Github和Gitlab同时使用ssh
    动视是否磨灭了暴雪的灵魂?
    设计模式——面向对象设计原则
    算法~PBKDF2-SHA让密码更安全
    【JVM深层系列】「官方技术翻译」《A FIRST LOOK INTO ZGC》初探JVM-ZGC垃圾回收器
    HTML <u> 标签
  • 原文地址:https://blog.csdn.net/u012124438/article/details/127916768