0-1背包问题解法(动态规划、分支限界法(回溯法、剪枝法)、贪心算法)

本文主要讲解0-1背包问题的三种解法:

  • 动态规划
  • 分支限界法(回溯法、剪枝法)
  • 贪心算法

什么是0-1背包问题

  • 给定n个重量为w1,w2,w3…wn,其价值为v1,v2,v3…vn的物品和容量为C的背包,求这个物品中一个最有价值的子集,使得在满足背包的容量的前提下,包内的总价值最大

正文开始


动态规划

  • 源码:Backpack_Dynamic 和 测试案例
  • 主要思想
    • 构造二维矩阵,进行试探性的取值
    • 状态转换方程:最优解=Math.max(前一位最优解,当前值+【背包当前重量-物品重量】的价值)
  • 主要代码
private int count(Goods[] goods, int packageweight) {
    //价值矩阵,列:背包的重量,行:加入的物品
    bestvalue = new int[packageweight + 1][goods.length + 1];
    //逐层规划,外层循环表示背包重量增加
    for (int i = 1; i <= packageweight; i++) {
        //内层循环,遍历物品
        for (int j = 1; j <= goods.length; j++) {
            //如果放入值比背包总重量还大,放弃
            if (goods[j - 1].weight > i) {
                bestvalue[i][j] = bestvalue[i][j - 1];
            } else {
                bestvalue[i][j] = Math.max(
                        bestvalue[i][j - 1],
                        bestvalue[i - goods[j - 1].weight][j - 1] + goods[j - 1].prices
                );
            }
        }
    }
    return bestvalue[packageweight][goods.length];
}
  • 注意事项

分支限界法(回溯法、剪枝法)

  • 源码:Backpack_Branch.java 和 测试案例
  • 主要思想
    • 通过不断的排列组合,得到最合适的物品装入序列
    • 通过背包重量和实际重量进行剪枝操作。
  • 主要代码
public void count(int depth) {
    if (BackpackRealWeight > BackpackWeight) {
        return;
    }
    BackpackValue = Math.max(BackpackValue, tempValue);
    for (int i = depth; i < goods.length; i++) {
        tempValue += goods[i].prices;
        BackpackRealWeight += goods[i].weight;
        //注意此处是i+1,不是depth+1
        count(i + 1);
        tempValue -= goods[i].prices;
        BackpackRealWeight -= goods[i].weight;
    }
}
  • 注意事项
    • 递归的深度,不是depth+1(容易引起死循环),而是当前的循环值。

贪心算法

  • 源码:Backpack_Greedy 和 测试案例
  • 主要思想
    • 将物品按照价值/重量,进行排序,当价值越大,重量越低的时候,物品价值率越高。
    • 不断加如价值率最高的物品,直到背包装不下。
  • 主要代码
public int Backpack(Integer[] goodsvalue, Integer[] weight, int packageweight) {
    if (!check(goodsvalue, weight, packageweight)) {
        return -1;
    }
    BackpackValue = 0;
    BackpackRealWeight = packageweight;
    goods = getGoods(goodsvalue, weight);
    InsertSort.sortMethodT(goods);
    for (int i = goodsvalue.length - 1; i >= 0; i--) {
        if (packageweight >= goods[i].weight) {
            BackpackValue += goods[i].prices;
            packageweight -= goods[i].weight;
        }
    }
    BackpackRealWeight = BackpackRealWeight - packageweight;
    return BackpackValue;
}
  • 注意事项
    • 排序算法的选择
    • 贪心算法不一定最优,但是比较快

你可能感兴趣的:(数据结构和算法及其应用,动态规划,贪心算法,Java,数据结构)