分支界限法解装载问题和解01背包问题十分类似,都是建立树之后广度优先遍历各结点,建立队列,约束条件是第一艘货船的承载能力,最后选择承载重量最大的一个组合,然后将剩余物品全部放在第二艘货船,判断是否可以装下,可以获得结果。

package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Created by saishangmingzhu on 2018/11/30.
 */
public class BinPackingProblem {

    public static void main(String[] arg) {
        new BinPackingProblem().branchAndBoundMethod();
    }

    /**
     * 分支界限法-队列式
     */
    public void branchAndBoundMethod() {
        int rucksackWeight1=10;
        int rucksackWeight2=10;
        List<Goods> goodsList=new ArrayList<>();
        goodsList.add(new Goods("书",1));
        goodsList.add(new Goods("足球",3));
        goodsList.add(new Goods("大箱子",7));
        goodsList.add(new Goods("macbook",3));
        goodsList.add(new Goods("iphone",1));
        goodsList.add(new Goods("礼盒",5));
//        //装不下的情况
//        goodsList.add(new Goods("书",2));
//        goodsList.add(new Goods("足球",9));
//        goodsList.add(new Goods("大箱子",9));
        int allWeight=0;
        for (Goods goods:goodsList){
            allWeight=allWeight+goods.getWeight();
        }
        if (allWeight>rucksackWeight1+rucksackWeight2){
            System.out.println("物品总重量已超出两货船总承载");
            return;
        }
        int goodsListSize=goodsList.size();
        //【1】定义二叉树的节点,包括左右子节点、剩余空间、当前总价值
        //【2】起始根节点
        Node root=new Node();
        root.setSurplusWeight(rucksackWeight1);
        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);
            int nextLevel=parentNode.getLevel()+1;
            if (nextLevel>goodsListSize){
                queueLeafNodeList.add(parentNode);
            } else {
                Goods g = goodsList.get(parentNode.getLevel());
                int surplus = parentNode.getSurplusWeight() - g.getWeight();
                if (surplus >= 0) {
                    Node node = new Node();
                    node.setLevel(nextLevel);
                    node.setSurplusWeight(surplus);
                    node.getGoodsList().addAll(parentNode.getGoodsList());
                    node.getGoodsList().add(g);
                    queueNodeList.add(node);
                }
                Node node = new Node();
                node.setLevel(nextLevel);
                node.setSurplusWeight(parentNode.getSurplusWeight());
                node.getGoodsList().addAll(parentNode.getGoodsList());
                queueNodeList.add(node);
            }
            queueNodeList.remove(0);
        }
        Collections.sort(queueLeafNodeList, new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {
                int surplus=o1.getSurplusWeight()-o2.getSurplusWeight();
                if (surplus<0)
                    return -1;
                else if (surplus>0)
                    return 1;
                return 0;
            }
        });
        Node first=queueLeafNodeList.get(0);
        System.out.println();
        if (allWeight-(rucksackWeight1-first.getSurplusWeight())<=rucksackWeight2){
            System.out.println("两货船可以装下所有物品");
            System.out.println("第一艘货船需装如下物品,其余物品装第二艘货船");
            List<Goods> goodsList1=first.getGoodsList();
            for (Goods goods:goodsList1){
                System.out.print(goods.getName()+",");
            }
            System.out.println();
        }
        else {
            System.out.println("两货船无法装下所有物品");
        }
    }


    class Goods{
        private String name;
        private int weight;

        public Goods(String name, int weight) {
            this.name = name;
            this.weight = weight;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getWeight() {
            return weight;
        }

        public void setWeight(int weight) {
            this.weight = weight;
        }
    }

    class Node{
        private int surplusWeight;
        private Node leftNode;
        private Node rightNode;
        private int level;
        private List<Goods> goodsList=new ArrayList<>();

        public int getLevel() {
            return level;
        }

        public void setLevel(int level) {
            this.level = level;
        }

        public int getSurplusWeight() {
            return surplusWeight;
        }

        public void setSurplusWeight(int surplusWeight) {
            this.surplusWeight = surplusWeight;
        }

        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;
        }

        public List<Goods> getGoodsList() {
            return goodsList;
        }

        public void setGoodsList(List<Goods> goodsList) {
            this.goodsList = goodsList;
        }
    }
}