首先初始化总容量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 =