分支界限法和回溯法很像,不一样之处是回溯法使用深度优先搜索,而分支界限法使用的是广度优先搜索,并使用了队列来记录每次有有效结点,经过入队出队的方式遍历有效结点。分支界限法在从活结点选择下一扩展结点时的不一样方法致使不一样分支界限法,常见的有队列分支界限法和优先队列分支界限法,这里以队里分支界限法为例。java
下边的代码设计有部分比较难理解,这里作个特别说明:使用分支界限法解01背包时,由于同层结点的子结点其实都是同一个物品的“装”与“不装”两个状态,因此经过记录结点的深度(即物资的位置)构建了虚拟的树(这里只的虚拟树是指每一个结点并无保存和父结点或子结点的关系,因此没法经过指针或是java里的属性值遍历树)。这种设计方式避免了构建树的过程,能够直接经过逻辑判断遍历虚拟树。
node
package test; import java.util.ArrayList; import java.util.List; /** * Created by saishangmingzhu on 2018/11/26. */ public class Rucksack { //【1】输入背包容量 //【2】输入物品体积及价值 public static void main(String[] arg) { new Rucksack().branchAndBoundMethod(); } /** * 分支界限法-队列式 */ public void branchAndBoundMethod() { int rucksackV=10; List<Goods> goodsList=new ArrayList<>(); goodsList.add(new Goods("书",1,2)); goodsList.add(new Goods("足球",3,4)); goodsList.add(new Goods("大箱子",7,2)); goodsList.add(new Goods("macbook",3,6)); goodsList.add(new Goods("iphone",1,5)); goodsList.add(new Goods("礼盒",5,3)); goodsList.add(new Goods("小箱子",4,2)); int goodsListSize=goodsList.size(); //【1】定义二叉树的结点,包括左右子结点、剩余空间、当前总价值 //【2】起始根结点 Node root=new Node(); root.setSurplusV(rucksackV); root.setWorth(0); root.setLevel(0); Node parentNode=root; //【3】定义队列 List<Node> queueNodeList=new ArrayList<>(); List<Node> queueLeafNodeList=new ArrayList<>(); queueNodeList.add(parentNode); while (queueNodeList.size()>0){ parentNode=queueNodeList.get(0); System.out.println("("+parentNode.getWorth()+","+parentNode.getSurplusV()+")"); int nextLevel=parentNode.getLevel()+1; if (nextLevel>goodsListSize){ queueLeafNodeList.add(parentNode); } else { Goods g = goodsList.get(parentNode.getLevel()); int surplus = parentNode.getSurplusV() - g.getVolume(); if (surplus >= 0) { Node node = new Node(); node.setLevel(nextLevel); node.setSurplusV(surplus); node.setWorth(parentNode.getWorth() + g.getWorth()); queueNodeList.add(node); } Node node = new Node(); node.setLevel(nextLevel); node.setSurplusV(parentNode.getSurplusV()); node.setWorth(parentNode.getWorth()); queueNodeList.add(node); } queueNodeList.remove(0); } int maxV=0; for (Node node:queueLeafNodeList){ System.out.print(node.getWorth()+","); if (maxV<node.getWorth()){ maxV=node.getWorth(); } } System.out.println(); System.out.println(maxV); } } class Goods{ private String name; private int volume; private int worth; public Goods(){} public Goods(String n,int v,int w){ this.name=n; this.volume=v; this.worth=w; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getVolume() { return volume; } public void setVolume(int volume) { this.volume = volume; } public int getWorth() { return worth; } public void setWorth(int worth) { this.worth = worth; } } class Node{ private int surplusV; private int worth; private int level; public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public int getSurplusV() { return surplusV; } public void setSurplusV(int surplusV) { this.surplusV = surplusV; } public int getWorth() { return worth; } public void setWorth(int worth) { this.worth = worth; } }