分支界限法和回溯法很像,不一樣之處是回溯法使用深度優先搜索,而分支界限法使用的是廣度優先搜索,並使用了隊列來記錄每次有有效結點,經過入隊出隊的方式遍歷有效結點。分支界限法在從活結點選擇下一擴展結點時的不一樣方法致使不一樣分支界限法,常見的有隊列分支界限法和優先隊列分支界限法,這裏以隊裏分支界限法爲例。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; } }