回溯算法类似于遍历的求解,但不同于无脑遍历的的地方是它在每一步都判断是否满足约束条件,及回溯点,所以可以理解为有条件的遍历。使用回溯算法求解01背包最优解时需要建立二叉树,树有业务意义的深度为物品数量n,加上根节点总深度为n+1,除了终端节点外,每个叶子节点都有左右两个children节点,left children定义为装入当前物品的情况,right children为不装入当前物品的情况,节点拥有“剩余最大容量”和“当前价值”两个属性,回溯点就是当剩余最大容量无法装入当前物品,或当前物品已是终端节点。
package test; import java.util.ArrayList; import java.util.List; /** * Created by saishangmingzhu on 2018/11/26. */ public class Rucksack { private List<Node> nodeList=new ArrayList<>(); //【1】输入背包容量 //【2】输入物品体积及价值 public static void main(String[] arg) { new Rucksack().backtracking(); } /** * 回溯算法 */ public void backtracking(){ 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)); //【1】定义二叉树的节点,包括左右子节点、剩余空间、当前总价值 //【2】起始根节点 Node root=new Node(); root.setSurplusV(rucksackV); root.setWorth(0); Node parentNode=root; again(goodsList, parentNode, 0); int maxV=0; for (Node node:nodeList){ System.out.print(node.getWorth()+","); if (maxV<node.getWorth()){ maxV=node.getWorth(); } } System.out.println(); System.out.println(maxV); } private void again(List<Goods> goodsList, Node parentNode, int i) { if (i>=goodsList.size()){ nodeList.add(parentNode); return; } Goods g=goodsList.get(i); //【1】左节点 int surplus=parentNode.getSurplusV()-g.getVolume(); if (surplus>=0){ Node leftNode=new Node(); leftNode.setSurplusV(surplus); leftNode.setWorth(parentNode.getWorth()+g.getWorth()); parentNode.setLeftNode(leftNode); again(goodsList, leftNode, i+1); } //【2】右节点,右节点复制父节点数据 Node rightNode=new Node(); rightNode.setSurplusV(parentNode.getSurplusV()); rightNode.setWorth(parentNode.getWorth()); parentNode.setRightNode(rightNode); again(goodsList, rightNode, i+1); } } 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 Node leftNode; private Node rightNode; 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; } public Node getLeftNode() { return leftNode; } public void setLeftNode(Node leftNode) { this.leftNode = leftNode; } public Node getRightNode() { return rightNode; } public void setRightNode(Node rightNode) { this.rightNode = rightNode; } }