(十二)动态规划--01背包

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jiangshangchunjiezi/article/details/91044077

贼,夜入豪宅,可偷之物甚多,而负重能力有限,偷哪些才更加不枉此行(价值)?

抽象的话,就是:

给定一组多个(n)物品,每种物品都有自己的重量(w_i)和价值(v_i),在限定的总重量/总容量(C)内,选择其中若干个(也即每种物品可以选0个或1个),设计选择方案使得物品的总价值最高。

 更加抽象的话:

给定正整数\{(w_i,v_i)\}_{1\leq i\leq n}、给定正整数C,求解0-1规划问题:

\max \sum_{i=1}^{n}{x_iv_i} , s.t. \sum_{i=1}^{n}{x_iw_i}\leq C , x_i\in\{0,1\} 。(在限重情况下,价值最大,其中物品不可切割)

表达式中各个符号的具体含义:

定义子问题 \mathbf{\text{P(i, W)}} 为:在前 i 个物品中挑选总重量不超过 W 的物品,每种物品至多只能挑选1个,使得总价值最大;这时的最优值记作 m(i,W) ,其中 1\leq i\leq n , 1\leq W\leq C 。

考虑第 i 个物品,无外乎两种可能:选,或者不选。

  • 不选的话,背包的容量不变,改变为问题 \mathbf{{P(i-1, W)}} ;
  • 选的话,背包的容量变小,改变为问题 \mathbf{{P(i-1, W-w_i)}} 。

最优方案就是比较这两种方案,哪个会更好些:

m(i,W)=\max\{m(i-1,W),m(i-1,W-w_i)+v_i\} 。

https://blog.csdn.net/sinat_34022298/article/details/77653693    对这个转移公式进行讲解,这里简单说明

动态规划是“全局最优解包含局部最优解”,所以要求最终的要m(n,c)要求出这个数组之前的数据

假设容量C=3  体积:5  4  3

d(i,j):前i个宝石转到剩余体积为j的背包中能达到的最大价值

d(2,7) --d(3,10)

若放入3号,则d(2,10-3)+12=d(2,7)+12

若不放3号,则d(2,10)

然后考虑max即可

“填二维表”的动态规划方法

当逐步推出表中每个值的大小,那个最大价值就求出来了。推导过程中,注意一点,最好逐行而非逐列开始推导,先从编号为1的那一行,推出所有c[1][m]的值,再推编号为2的那行c[2][m]的大小。这样便于理解。

思路厘清后,开始编程序,Java代码如下所示

import java.util.*;

public class test {

    public static int getMaxValue(int[] weight, int[] value, int w, int n) {
        int[][] table = new int[n + 1][w + 1];
        for (int i = 1; i <= n; i++) { //物品
            for (int j = 1; j <= w; j++) {  //背包大小
                if (weight[i] > j) {        
                        //当前物品i的重量比背包容量j大,装不下,肯定就是不装
                    table[i][j] = table[i - 1][j];
                    // System.out.print(table[i][j]+ " ");
                } else { //装得下,Max{装物品i, 不装物品i}
                    table[i][j] = Math.max(table[i - 1][j], table[i - 1][j - weight[i]] + value[i]);
                    //System.out.print(table[i][j]+ " ");
                }
            }
            // System.out.println();
        }
        return table[n][w];
    }

    public static void main(String[] args) {

        int n = 5, w = 10;                    //物品个数,背包容量
        int[] value = {0, 6, 3, 5, 4, 6};     //各个物品的价值
        int[] weight = {0, 2, 2, 6, 5, 4};    //各个物品的重量
        System.out.println(getMaxValue(weight,value,w,n));

    }
}

猜你喜欢

转载自blog.csdn.net/jiangshangchunjiezi/article/details/91044077