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

本文详细介绍了0-1背包问题的三种经典解法:动态规划、回溯法(分支限界法)和贪心算法。动态规划通过构造二维矩阵实现最优解;回溯法通过排列组合和剪枝操作找到合适物品序列;贪心算法按价值/重量比例排序物品,优先选择价值率高的。每种方法都有其适用场景和效率考量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要讲解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;
}
  • 注意事项
    • 排序算法的选择
    • 贪心算法不一定最优,但是比较快
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值