背包问题

问题描述

假设你是一个贪婪的小偷,背着可以装35磅重东西的背包,在商场伺机偷窃各种可以装入背包的商品。

背包问题_第1张图片

你力图往背包中装入价值最高的商品,你会用哪种算法呢?

同样你也可以采取贪心策略,这非常简单。

  • ①盗窃可装入背包的最贵商品。
  • ②再盗窃还可装入背包的最贵商品,以此类推。

只是这次这种贪心策略并不好使了,例如你可以盗窃以下三种商品:

背包问题_第2张图片

你的背包可以装35磅的东西。其中音响最贵,你把它偷了,但是背包没有空间装其他东西了。

背包问题_第3张图片

这样你偷到了价值3000美元的东西。但是,如果不是偷音响,而是偷笔记本电脑和吉他,那么将会偷到价值3500美元的东西!

背包问题_第4张图片

在这里,贪心策略显然不能获得最优解。但非常接近。

从这个示例中或许还可以得到如下启示:在有些情况下,完美是优秀的敌人。有时候,你只需找到一个能够大致解决问题的算法,此时贪心算法正好可以派上用场,因为它实现起来很容易,得到的结果又与正确结果相当接近。

代码实现

有了上面的思想,那么实现代码就变得简单了,主要代码如下:

private static int bag_problem(int[] values, int[] weights) {
    int currentSpace = totalSpace;       // 当前背包剩余的空间
    int currentValue = 0;                // 当前背包的价值
    int goodsNumber = values.length;    // 商品数量

    // 用来表示商品是否被装载,0表示没有,1表示装载
    int[] isLoad = new int[goodsNumber];
    for (int i = 0;i < goodsNumber;i++) {
        isLoad[i] = 0;
    }   // end for

    while (true) {
        int maxValue = 0;
        int postion = 0;        // 记录位置信息

        for (int j = 0; j < goodsNumber; j++) {
            // 如果物品已经被装载则跳过
            if (isLoad[j] == 1) continue;

            if (values[j] > maxValue && currentSpace >= weights[j]) {
                maxValue = values[j];
                postion = j;
            }
        }   // end inner for:找到了当前最大的values值

        // 背包已经装不下东西了
        if (maxValue == 0) break;

        // 装载物品
        currentSpace = currentSpace - weights[postion];
        currentValue += values[postion];
        isLoad[postion] = 1;
    }

    return currentValue;
}

参考资料:《算法图解》—— Aditya Bhargava 著

欢迎转载,转载请注明出处!
ID:@我没有三颗心脏
github:wmyskxz
欢迎关注公众微信号:wmyskxz_javaweb
分享自己的Java Web学习之路以及各种Java学习资料

你可能感兴趣的:(背包问题)