• 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
  • 相关阅读:
    XenServer 6.2部署教程
    logstash 采集的文件mv后
    北京十大知名律师事务所排名(市场调研前十)
    第十五届蓝桥杯总结
    Element Plus中Cascader 级联选择器(选择任意一级选项 - 更改下拉框选中方式)
    【Linux开发基础知识】shell语法整理
    SpringBoot 整合Mybatis
    已解决python -m pip install --upgrade pip命令升级报错
    【无公网IP】在公网环境下Windows远程桌面Ubuntu 18.04
    剑指 Offer II 034. 外星语言是否排序
  • 原文地址:https://blog.csdn.net/u012124438/article/details/127916768