队列式分支限界算法解决装载问题-Java实现

装载问题的问题提出是,有一批共n个集装箱要装上2艘载重量分别为 和 的轮船,其中集装箱i的重量为 ,且 。问是否有一个合理的装载方案能将这n个集装箱装上这两艘轮船。该问题形式化描述为:
在这里插入图片描述
设n=5, C1 =120,C2 =80, w= {60,40,10,30,50} 。采用队列式分支限界算法解决该问题。

import java.util.LinkedList;
import java.util.Queue;

public class FIFOLoading {
    //结点类
    private  class  Node{
        Node parent;//该结点的父节点
        int weight;//该结点的重量
        Boolean isLeftChild;//该结点的父节点的左子节点
        public Node(Node parent,int wt,Boolean isLeftChild){
            this.parent=parent;
            this.weight=wt;
            this.isLeftChild=isLeftChild;
        }
    }
    int n;//集装箱的数量
    int w[];//集装箱的重量数组
    int c;//船1的承载量

    Node bestE=null;//最优叶子结点的父节点
    int wt=0;//当前结点和之前的结点之和

    int bestW=0;//最优重量和
    int bestx[];//最优决策

    public FIFOLoading(int n, int w[], int c){
        this.n=n;
        this.c=c;
        this.w=w;
        this.bestx=new int[n+1];
    }
//    活结点队列
    Queue<Node> queue=new LinkedList();
    private void EnQueue(int i,Node parent,int weight,Boolean leftChild){
        //达到叶子结点
        if(i==n){
            //重量和==bestW
            if (weight == bestW) {
                //  叶子结点的父节点
                bestE = parent;
                // 更新最优决策数组的最后一项
                bestx[n] = (bestE.isLeftChild) ? 1 : 0;
            }
        }else{
            // 创建新的结点
            Node b=new Node(parent,weight,leftChild);
            //添加结点到队列中
            queue.add(b);
        }
    }
    private void  maxLoding(){
        int i=1;//当前层数
        //创建根结点A
        Node A=new Node(null,0,true);
        Node e=A;//e记录即将放入队列的结点
        bestE=A;
        queue.add(null);
        int residue=0;//剩余集装箱重量
        for(int j=2;j<=n;j++){
            residue+=w[j];
        }
        int ew=0;//当前拓展结点的重量
        while (true){
            //w[i]为将扩展结点所相应的载重量
            wt=ew+w[i];
            //检查左子结点 可行则装入队列
            if(wt<=c){
                //更新最优重量
                if(wt>bestW){
                    bestW=wt;
                }
                //以左子节点身份进入
                EnQueue(i,e,wt,true);
            }
            // 检测右结点
            if(ew+residue>=bestW){
                EnQueue(i,e,ew,false);
            }
            //取队列的第一个结点
            e = queue.poll();
            //e=null表示同层结点尾部
            if(e==null){
                if(queue.isEmpty()){
                    break;
                }
                queue.add(null);
                //更新当前结点
                e=queue.remove();
//                进入下一层
                i++;
                residue-=w[i];
            }
            //更新扩展结点所相应的载重量
            ew=e.weight;
        }
        //构造当前最优解
        for (int j = n - 1; j > 0; j--) {
            bestx[j] = (bestE.isLeftChild) ? 1 : 0;
            bestE = bestE.parent;
        }
    }
    public static  void main(String args[]){
        int n=5;
        int c=120;//船1承载重量
        int[] w= {0,60,40,10,30,50};//集中箱i的重量
        FIFOLoading fifoLoading=new FIFOLoading(n,w,c);
        fifoLoading.maxLoding();
        System.out.println("船1最优装载量:"+fifoLoading.bestW);
        System.out.println("决策数组为:");
        for(int i=1;i<=n;i++)
            System.out.print(fifoLoading.bestx[i]+" ");
    }
}

运行结果
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值