java - 算法 -动态规划 - 01背包

对着背影说爱祢 提交于 2019-12-04 15:38:36

- -一个月前没搞明白,最近再学习一遍搞明白了。

 

问题:

给定3个物品

a 价值1000, 重量1kg

b 价值2000, 重量4kg

c 价值1500, 重量3kg

用容量为4kg的背包最多可以装价值多少的物品?

 

背包问题就是类似这种给定容量求最优解的问题,有很多种,这里说的是01背包问题。

01背包:所有物品只有一个,只所以背包中任意物品的的数量只可能是0 或者 1。

 

动态规划思路:

当前情况的思考建立在之前的思考之上。

01背包的逻辑思考过程: - -之前网上各种版本都是来个表格然后就开始代码了。。。一脸懵逼

我先假设只考虑第1个物品a,这样我就可以得到:

背包最大容量为0, 1,2,3,4时,最大价值为0, 1000,1000,1000,1000       

 

然后再考虑前2个物品(a 和 b)

先考虑:

背包最大容量为0,1,2,3时, b装不下,所以还是用只考虑前1个物品时的策略,可以得到0, 1000,1000,1000

背包最大容量为4时,b可以装下了,这时候就面临选择,比较:是考虑往背包中加入b时的价值高,   还是只考虑前1个物品时的价值高。

1. 假设加入了b: 背包剩余可用的容量是:    背包最大容量 - b占用的容量 = 4 - 4 = 0; 此时背包物品的最大价值是:b的价值剩余容量所能存放的还没加入b之前的最大值。

而剩余容量所能存放的还没加入b之前的最大值,也就是只考虑a的情况下的值,我们在之前那一行中已经列出来的背包容量为所有情况下的最大价值已经全部列出来了,此时可以利用上一行得到。

此时加入加入了b,那么背包最多还有0kg物品可以用

而上面已经得到: 背包最大容量为0, 1,2,3,4时,最大价值为0, 1000,1000,1000,1000 

所以此时可以得到,如果把b加入背包,那么 最大价值是 b的价值 + 背包容量为0时,只考虑b之前的物品时,背包能存放的最大价值 = 2000 + 0;

 2. 假设不把b放入背包, 背包的最大价值 等于 只考虑b之前物品时的最大价值,也就是 背包最大容量所能存放的还没加入b之前的最大值

比较1 和 2 两种策略谁的值大,那么谁就是考虑目前所有物品时的最大价值。 也就是2000

此时背包最大容量为0,1,2,3,4时,对应最大值为 0,1000,1000,1000,2000

 

然后c和b的考虑模式一样

先试试加入c,此时背包除去c的占用容量后可用容量为4 -3 = 1, 此时背包物品的最大价值是:c的价值 + 剩余容量所能存放的还没加入c之前的最大值。 根据上一步得到背包最大容量为1时,最大价值为1000

所以加入c最大价值为 1500 + 1000 = 2500;

不加入c时,最大价值为上一步考虑b之后,背包容量为 4 时的最大价值: 2000;

比较后可以得到,加入c时的价值更高,得到2500;

。。。

 

如果还有别的物品,依次类推直到所有物品都考虑完毕。

 

package dynamic;

public class bag {
    //01背包问题
    public static void main(String[] args){
        int[] v = {0, 1000, 2000, 1500, 2000}; //物品价格,第0个物品价格为0, 单纯为了逻辑清楚,这样index = 物品编号
        int[] w = {0, 1, 4, 3, 2};  //物品需要的容量,第0个物品重量为0
        int capacity = 4; // 背包最大可以使用的容量
        System.out.println("最多可在背包中存放价值为:" + maxValue(v, w, capacity) + "的物品");
    }

    public static int maxValue(int[] v, int[] w, int capacity){
        int[][] value = new int[v.length][capacity + 1]; // value[i][j]表示只考虑前i个物品,在能用j 容量的情况下最多可以放价值为value[i][j]的东西
        for(int i = 1; i < v.length; i++){ //从第1个物品开始,依次推导
            for(int j = 1; j <= capacity; j++) { //从最大容量是1到背包最大值,依次推导
                if (w[i] > j) {
                    value[i][j] = value[i - 1][j]; //如果新加入考虑的物品的重量已经超过了背包最大容量,则不用考虑,依然使用只考虑它之前那些物品的方案
                } else {
                    value[i][j] = Math.max(value[i - 1][j], v[i] + value[i - 1][j - w[i]]);
                }
            }
        }
        for(int i = 0; i < value.length; i++){
            for(int j =0; j < value[i].length; j++){
                System.out.print(value[i][j] + " ");
            }
            System.out.println();
        }
        return value[v.length - 1][capacity];
    }

}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!