美文网首页
背包问题

背包问题

作者: PC_Repair | 来源:发表于2019-11-05 11:20 被阅读0次

一、01 背包问题

题目

有 N 件物品和一个容量为 V 的背包。第 i 件物品的重量是 w[i],价值是 v[i]。求解将哪些物品装入背包可使价值总和最大。

二维动态规划:

  • 最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。

  • 状态转移方程

    //dp[i][j] 表示前 i 件物品恰放入一个容量为 j 的背包可以获取的最大值
    dp[i][j] = max{dp[i-1][j], dp[i-1][j-w[i]] + v[i]}
  • 代码
    public static void main(String[] args) {
        int[] w = new int[]{2, 3, 4, 5}; // 商品的体积 2 3 4 5
        int[] v = new int[]{3, 4, 5, 6}; // 商品的价值 3 4 5 6
        int bagV = 8; // 背包大小
        int[][] dp= new int[w.length+1][bagV+1];  // 动态规划表

        for (int i = 0; i < w.length; i++) { // 第 i 个物品
            for (int j = 1; j <= bagV; j++) { // 容量
                // 状态转移方程
                if (j < w[i]) {
                    dp[i+1][j] = dp[i][j];
                } else {
                    dp[i+1][j] = Math.max(dp[i][j], dp[i][j-w[i]] + v[i]);
                }
            }
        }

        for (int i = 0; i < dp.length; i++) {
            for (int j = 0; j < dp[0].length; j++) {
                System.out.print(dp[i][j] + " ");
            }
            System.out.println();
        }

        // 最优解
        System.out.println(dp[w.length][bagV]);
    }

二、完全背包问题

题目

有 N 种物品和一个容量为 V 的背包,每种物品都有无限件可用。第 i 种物品的重量是 w[i],价值是 v[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

状态转移方程:

  • 类似 01 背包问题,但是取策略不是取或不取,而是取 0 件、1件、2件...等
//dp[i][j] 表示前 i 件物品放入一个容量为 j 的背包可以获取的最大值
dp[i][j] = max{dp[i-1][j-k*w[i]] + k*v[i] | 0<=k*w[i]<=j}

代码:

    public static void main(String[] args) {
        int[] w = new int[]{2, 3, 4, 5}; // 商品的体积 2 3 4 5
        int[] v = new int[]{3, 4, 5, 6}; // 商品的价值 3 4 5 6
        int bagV = 8; // 背包大小
        int[][] dp= new int[w.length+1][bagV+1];  // 动态规划表

        for (int i = 0; i < w.length; i++) { // 第 i 个物品
            for (int j = 1; j <= bagV; j++) { // 容量
                // 状态转移方程
                for (int k = 0; k*w[i] <= j; k++) {
                    dp[i+1][j] = Math.max(dp[i+1][j], dp[i][j-k*w[i]] + k*v[i]);
                }
            }
        }

        for (int i = 0; i < dp.length; i++) {
            for (int j = 0; j < dp[0].length; j++) {
                System.out.print(dp[i][j] + " ");
            }
            System.out.println();
        }

        // 最优解
        System.out.println(dp[w.length][bagV]);
    }

三、多重背包问题

题目

有N种物品和一个容量为 V 的背包。第i种物品最多有 n[i] 件可用,每件重量是 w[i],价值是 v[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

基本算法

和完全背包问题很类似。基本的方程只需将完全背包问题的方程略微一改即可,因为对于第 i 种物品有 n[i]+1 种策略:取 0 件,取 1 件……取 n[i] 件。令dp[i][j] 表示前 i 种物品恰放入一个容量为 j 的背包的最大权值,则有状态转移方程:

//dp[i][j] 表示前 i 件物品放入一个容量为 j 的背包可以获取的最大值
dp[i][j] = max{dp[i-1][j-k*w[i]] + k*v[i] | 0<=k<=n[i] && 0<=k*w[i]<=j}

代码:

    public static void main(String[] args) {
        int[] w = new int[]{2, 3, 4, 5}; // 商品的体积 2 3 4 5
        int[] v = new int[]{3, 4, 5, 6}; // 商品的价值 3 4 5 6
        int[] n = new int[]{1, 3, 2, 1}; // 每件商品的数量

        int bagV = 8; // 背包大小
        int[][] dp= new int[w.length+1][bagV+1];  // 动态规划表

        for (int i = 0; i < w.length; i++) { // 第 i 个物品
            for (int j = 1; j <= bagV; j++) { // 容量
                // 状态转移方程
                for (int k = 0; k*w[i] <= j && k <= n[i]; k++) {
                    dp[i+1][j] = Math.max(dp[i+1][j], dp[i][j-k*w[i]] + k*v[i]);
                }
            }
        }

        for (int i = 0; i < dp.length; i++) {
            for (int j = 0; j < dp[0].length; j++) {
                System.out.print(dp[i][j] + " ");
            }
            System.out.println();
        }

        // 最优解
        System.out.println(dp[w.length][bagV]);
    }

四、混合三种背包问题

题目:

将前面三种背包问题混合起来,也就是说,有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包)。

01背包与完全背包的混合

一类物品只能取一次,另一类物品可以取无限次。

解决方法:判断物品种类从而进入不同的循环。

for i=1..n
    if 第 i 件物品属于 01 背包
        for j=1..bagV
            dp[i][j] = max{dp[i-1][j], dp[i-1][j-w[i]] + v[i]}
    if 第 i 件物品属于 完全背包问题
        for j=1..bagV
            dp[i][j] = max{dp[i-1][j], dp[i-1][j-k*w[i]] + k*v[i] | 0<=k*w[i]<=j}
    if 第 i 件物品属于 多重背包问题
        for j=1..bagV
            dp[i][j] = max{dp[i-1][j], dp[i-1][j-k*w[i]] + k*v[i] 0<=k<=n[i] && 0<=k*w[i]<=j}

五、二维费用的背包问题

题目

对于每件物品,具有两种不同的费用,选择这件物品必须同时付出这两种代价,对于每种代价都有一个可付出的最大值(即背包容量)。

设两种代价分别为 w1[i], w2[i], 物品的价值为 v[i]

状态转移方程

dp[i][j][k] = max{dp[i-1][j][k], dp[i-1][j-w1[i]][k-w2[i]] + v[i]}

小结

当发现熟悉的动态规划题目变形而来的题目时,在原来的状态中可以加一维度来满足新的限制是一种比较通用的方法。

六、分组的背包问题

相关文章

  • 背包问题(完全背包)

    动态规划合集: 1.矩阵链乘法2.投资组合问题3.完全背包问题4.01背包问题5.最长公共子序列 例题3——背包问...

  • Algorithm进阶计划 -- 动态规划(下)

    经典动态规划背包问题最长子序列问题 1. 背包问题 1.1 0-1 背包问题 0-1 背包问题,描述如下: 上面...

  • 背包问题

    0-1背包问题 问题 n个物体,它们各自有重量和价值,给定一个有容量的背包,如何让背包里装入的物体价值总和最大? ...

  • 背包问题

    问题描述 假如有一个能装下4磅的背包,如何从下列商品列表中选择商品填充背包,使价值达到最大: 动态规划 要解决背包...

  • 背包问题

    (1)0-1背包容量为10的背包,有5种物品,每种物品只有一个,其重量分别为5,4,3,2,1,其价值分别为1,2...

  • 背包问题

  • 背包问题

    01背包(物品只有一个) 有N件物品和一个容量为V的背包。第i建物品的费用是w[i],价值是v[i]。求解将哪些物...

  • 背包问题

    1. 01背包 状态说明:背包体积为v,物品个数为n,f[n,v]表示前n件物品加入背包的最大价值。c_i,w_i...

  • 背包问题

    01背包 优化空间复杂度,变为一维; 外循环依然是n从1->N, 注意内循环 v是从V->0,为什么内循环是V->...

  • 背包问题

    介绍 学习动态规划算法的经典例题。动态规划算法一般有3个特征1、最优化原理:最优解所包含的子问题的解也是最优的。2...

网友评论

      本文标题:背包问题

      本文链接:https://www.haomeiwen.com/subject/rxesbctx.html