运用分支定界法(分支限界法)解决01背包问题

首先初始化总容量capacity = 10、物品总数量number = 4
物品信息为【4,40】、【7、42】、【5、25】、【3、12】,分别为重量weight,价值value。
解决该题目运用到的数据结构有:优先队列、二叉树、存放物品基本信息的数组
这里主要就是构建二叉树,二叉树节点的属性有
weight(当前总容量)
value(当前总价值)
layer(当前层级,用来判断是否为叶子节点)
currentSolution(当前解,算出最大价值后,方便找出拿了哪些物品)
up(上限)
left(左孩子,取当前物品)
right(右孩子,不取当前物品)
在这里插入图片描述
树如下
在这里插入图片描述
说下各个节点的值是怎么算的


在这里插入图片描述
这是根节点,所以初始化weight为0、value为0、up为剩余的物品最有可能能取到的最大价值。所以up = 当前剩余容量 * (value / weight) = 10 * (40 / 4) = 100。layer层级为0。


在这里插入图片描述
取第一个物品时。weight = 第一个物品的weight = 4,value同理。layer层级为1,currentSolution为1(1代表取)
up = 当前总价值 + 当前剩余容量 * (第二个物品的value / 第二个物品的weight)= 40 + (10 - 4) * (42 / 7) = 76


在这里插入图片描述
不取第一个物品。weight = 0,value = 0。layer层级为1,currentSolution为0(0代表取)
up = 当前剩余容量 * (第二个物品的value / 第二个物品的weight)= 10 * (42 / 7) = 60


在这里插入图片描述
取第一个物品、取第二个物品。weight = 4 + 第二个物品weight = 4 + 7 = 11 > 最大容量10。所以该节点不用继续计算和保存。


在这里插入图片描述
取第一个物品、不取第二个物品。weight = 原来的weight = 4,value = 原来的value = 40,layer层级为2,currentSolution为10
up = 当前总价值value + 剩余容量 * (第三个物品的value / 第三个物品的weight)= 40 + (10 - 4) * (25 / 5) = 70


在这里插入图片描述
取第一个物品、不取第二个物品、取第三个物品。weight = 已有weight + 第三个物品weight = 4 + 5 = 9,value = 已有value + 第三个物品value = 40 + 25 = 65。layer层级为3,currentSolution为101。
up = 当前总价值value + 剩余容量 * (第四个物品的value / 第四个物品的weight)= 65 + (10 - 9) * (12 / 3) = 69


在这里插入图片描述
取第一个物品、不取第二个物品、取第三个物品、不取第四个物品。weight = 已有weight = 9,value同理。layer层级为4,currentSolution为1010。
因为layer = 物品总数量number = 4
所以up = 当前总价值value


其它的节点计算方式同理。所以根据以上方式,最后可以计算出一棵二叉树。再对其节点进行判断。
对于左右分支,我们并不知道最终答案是在哪个分支下面,所以两个分支都要判断,不过不能太盲目。应该有一个查找侧重点,因为答案在up值更大的节点下面可能性更大,所以我们有限查找up值较大的节点。这里就需要一个优先队列,把左右节点放入到队列中,up值大的放在前面,优先出队。
在这里插入图片描述


最后代码(注释就是思路)。一共有5个类,Backpack、BinaryTree、ItemInfo、Node、Main
ItemInfo.java

package com.aekc.algorithm.backpack;

/**
 * 物品基本信息
 */
public class ItemInfo {
   

    /**
     * 重量
     */
    private int weight;

    /**
     * 价值
     */
    private int value;

    public ItemInfo() {
   }

    public ItemInfo(int weight, int value) {
   
        this.weight = weight;
        this.value = value;
    }

    public int getWeight() {
   
        return weight;
    }

    public void setWeight(int weight) {
   
        this.weight = weight;
    }

    public int getValue() {
   
        return value;
    }

    public void setValue(int value) {
   
        this.value = value;
    }
}


Node.java

package com.aekc.algorithm.backpack;

/**
 * 分支定界法,节点属性
 */
public class Node extends ItemInfo implements Comparable {
   

    /**
     * 层级,用来判断是否为叶子节点
     */
    private int layer;

    /**
     * 当前解,算出最大价值后,方便找出拿了哪些物品
     */
    private String currentSolution;

    /**
     * 上限
     */
    private double up;

    /**
     * 取
     */
    private Node left;

    /**
     * 不取
     */
    private Node right;

    public Node() {
   }

    public int getLayer() {
   
        return layer;
    }

    public void setLayer(int layer) {
   
        this.layer = layer;
    }

    public String getCurrentSolution() {
   
        return currentSolution;
    }

    public void setCurrentSolution(String currentSolution) {
   
        this.currentSolution = currentSolution;
    }

    public double getUp() {
   
        return up;
    }

    public void setUp(double up) {
   
        this.up = up;
    }

    public Node getLeft() {
   
        return left;
    }

    public void setLeft(Node left) {
   
        this.left = left;
    }

    public Node getRight() {
   
        return right;
    }

    public void setRight(Node right) {
   
        this.right =
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值