0-1揹包問題-回溯算法

    回溯算法相似於遍歷的求解,但不一樣於無腦遍歷的的地方是它在每一步都判斷是否知足約束條件,及回溯點,因此能夠理解爲有條件的遍歷。使用回溯算法求解01揹包最優解時須要創建二叉樹,樹有業務意義的深度爲物品數量n,加上根節點總深度爲n+1,除了終端節點外,每一個葉子節點都有左右兩個children節點,left children定義爲裝入當前物品的狀況,right children爲不裝入當前物品的狀況,節點擁有「剩餘最大容量」和「當前價值」兩個屬性,回溯點就是當剩餘最大容量沒法裝入當前物品,或當前物品已經是終端節點。
java

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;
    }
}
相關文章
相關標籤/搜索