背包问题

我发现背包问题既棘手又有趣。 我敢肯定,如果您正在访问此页面,您已经知道了问题说明,但是只是为了完成本章:

问题:

给定一个最大容量为W和N的背包,每个背包都有自己的值和重量,将它们放入背包中,使最终内容物具有最大值。 kes!



背包

这是解释问题的一般方法-考虑一个小偷进入家中抢劫,他背着背包。 家里有固定数量的物品-每个物品都有自己的重量和价值-珠宝首饰,重量和重量比桌子高,价值少,但重量重。 为了给火上加油,小偷有一个老式的背包,容量有限。 显然,他不能将桌子分成两半,也不能将珠宝分成3/4分。 他要么接受要么离开。

范例:
Knapsack Max weight     :       W = 10 (units)

    Total items             :       N = 4

    Values of items         :       v[] = {10, 40, 30, 50}

    Weight of items         :       w[] = {5, 4, 6, 3}

粗略看一下示例数据可知,在权重最大为10的情况下,我们可以容纳的最大值为50 + 40 = 90(权重为7)。

方法:

最佳解决方案是使用动态编程-解决较小的背包问题,然后将其扩展为较大的问题。

让我们构建一个名为V(值数组)的Item x Weight数组:

V[N][W] = 4 rows * 10 columns

此矩阵中的每个值代表一个较小的背包问题。

基本情况1 :让我们以第0列为例。 这仅意味着背包的容量为0。 你能在他们身上抱什么? 没有。 因此,让我们用0填充它们。

基本情况2 :让我们以0行为例。 这仅表示房子中没有物品。 如果没有物品,您在背包里会做什么? 没事了! 全零。

Varray0

解:

  1. 现在,让我们开始逐行填充数组。 第1行和第1列是什么意思? 给定第一个项目(行),您能否将其容纳在容量为1(列)的背包中。 不。 第一项的权重为5。因此,让我们填写0。实际上,直到到达第5列(权重5),我们才能填写任何内容。
  2. 当我们到达第一行的第5列(代表权重5)时,这意味着我们可以容纳第1项。让我们在此处填写10(请记住,这是一个Value数组):


    Varray1

  3. 继续,对于权重6(第6列),我们是否可以容纳剩余重量为1(重量–该商品的重量=> 6 – 5)的任何其他东西。 嘿,记住,我们在第一个项目上。 因此,从直觉上讲,该行的其余部分也将是相同的值,因为我们无法为已获得的额外重量添加任何其他项目。


    Varray2

  4. 因此,当我们到达第三行的第4列时,会发生下一个有趣的事情。 当前的跑步重量为4。

我们应检查以下情况。

  1. 我们可以容纳项目2 –是的,我们可以。 项目2的权重为4。
  2. 没有第2项,当前重量的值是否更高? –检查上一行是否具有相同的重量。 不。 前一行*的内容为0,因为我们无法容纳重量为4的商品1。
  3. 我们可以容纳两件重量相同的物品,以使价值最大化吗? - 不。 减去Item2的权重后的剩余权重为0。

Varray3

为什么要上一行?

仅仅是因为权重为4的前一行本身是一个较小的背包解决方案,它给出了该权重在该点之前(穿越项目)可以累积的最大值。

举例说明

  1. 当前项目的值= 40
  2. 当前商品的重量= 4
  3. 剩下的权重= 4 – 4 = 0
  4. 检查上面的行(如果是项目1,则检查上面的项目;如果其余的行,则检查累积最大值)。 对于剩余重量0,我们是否可以容纳项目1? 简而言之,对于给定的权重,上面一行是否有任何值?

计算过程如下:

  1. 不带此项,取相同重量的最大值:
    previous row, same weight = 0
    
    => V[item-1][weight]
  2. 取当前商品的价值+我们可以用剩余重量容纳的价值:
    Value of current item
    + value in previous row with weight 4 (total weight until now (4) - weight of the current item (4))
    
    => val[item-1] + V[item-1][weight-wt[item-1]]

    两者之间的最大值为40(0和40)。

  3. 下一个也是最重要的事件发生在第9列和第2行。这意味着我们的权重为9,并且有两项。 查看示例数据,我们可以容纳前两个项目。 在这里,我们考虑几件事:
    1. The value of the current item = 40
    2. The weight of the current item = 4
    3. The weight that is left over = 9 - 4 = 5
    4. Check the row above.  At the remaining weight 5, are we able to accommodate Item 1.


    Varray4

因此,计算公式为:

  1. 不带此项,取相同重量的最大值:
    previous row, same weight = 10
  2. 取当前商品的价值+我们可以用剩余重量累计的价值:
    Value of current item (40)
    + value in previous row with weight 5 (total weight until now (9) - weight of the current item (4)) 
    
    = 10

    10比50 = 50。

解决所有这些较小的问题之后,我们只需要返回权重为10的V [N] [W] –项目4的值:

Varray5

复杂

分析解决方案的复杂性非常简单。 我们在N => O(NW)的循环中只有一个W循环

实现方式:

这是Java中的强制性实现代码:

class Knapsack {

    public static void main(String[] args) throws Exception {
        int val[] = {10, 40, 30, 50};
        int wt[] = {5, 4, 6, 3};
        int W = 10;

        System.out.println(knapsack(val, wt, W));
    }

    public static int knapsack(int val[], int wt[], int W) {

        //Get the total number of items. 
        //Could be wt.length or val.length. Doesn't matter
        int N = wt.length; 

        //Create a matrix. 
        //Items are in rows and weight at in columns +1 on each side
        int[][] V = new int[N + 1][W + 1]; 


        //What if the knapsack's capacity is 0 - Set
        //all columns at row 0 to be 0
        for (int col = 0; col <= W; col++) {
            V[0][col] = 0;
        }

        //What if there are no items at home.  
        //Fill the first row with 0
        for (int row = 0; row <= N; row++) {
            V[row][0] = 0;
        }

        for (int item=1;item<=N;item++){

            //Let's fill the values row by row
            for (int weight=1;weight<=W;weight++){

                //Is the current items weight less
                //than or equal to running weight
                if (wt[item-1]<=weight){

//Given a weight, check if the value of the current 
//item + value of the item that we could afford 
//with the remaining weight is greater than the value
//without the current item itself
                    V[item][weight]=Math.max (val[item-1]+V[item-1][weight-wt[item-1]], V[item-1][weight]);
                }
                else {
//If the current item's weight is more than the
//running weight, just carry forward the value
//without the current item
                    V[item][weight]=V[item-1][weight];
                }
            }

        }

        //Printing the matrix
        for (int[] rows : V) {
            for (int col : rows) {

                System.out.format("%5d", col);
            }
            System.out.println();
        }

        return V[N][W];

    }

}

翻译自: https://www.javacodegeeks.com/2014/07/the-knapsack-problem.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值