分支限界法 | 带期限作业排序 | Java实现

写在前面

欢迎讨论~


问题描述

允许作业有不同的处理时间,每个作业i与一个三元组联系(pi, di, ti)。
目标:n个作业的子集合J,J中的作业都能在相应的期限内完成,且不在J中的作业招致的罚款总额最小。
例:n=4,
(p1,d1,t1)=(5,1,1),
(p2,d2,t2)=(10,3,2),
(p3,d3,t3)=(6,2,1),
(p4,d4,t4)=(3,1,1),


Java 实现

main.java包含测试数据。
LCBB.java为算法实现主体。
Node.java是结点类。
NodeComparator.java用于排序。

//main.java
public class Main {
    public static void main(String[] args) {
        int p[]=new int[]{6,3,4,8,5};
        int t[]=new int[]{2,1,2,1,1};
        int d[]=new int[]{3,1,4,2,4};
        LCBB worker=new LCBB();
        worker.lcbb(p,d,t);
    }
}
//LCBB.java
import java.util.*;
public class LCBB {

    Vector<Integer> parent;
    LinkedList<Node> lifeNodes;
    int U;
    int pointNumber;
    int ans;
    void lcbb(int[]p,int[]d,int[]t)
    {
        //求惩罚最大值
        int n=p.length;
        int sumP=0;
        for(int x:p)
        {
            sumP+=x;
        }
        //初始化
        int[] newX;
        ans=0;
        pointNumber=0;
        parent=new Vector<Integer>();
        lifeNodes=new LinkedList<Node>();
        //配置初始结点
        Node aNode=new Node(pointNumber++,sumP,0,-1);
        aNode.setX(new int[p.length]);
        parent.add(-1);
        lifeNodes.add(aNode);
        Node childNode;//=new Node(pointNumber,sumP,0,-1);
        U=sumP;
        //开始添加儿子节点
        while (true)
        {
            for (int i = aNode.thisStep + 1, sumAbandon = 0; i < n; i++) {
                //配置孩子结点
                childNode = new Node(pointNumber++, aNode.getU() - p[i], aNode.getC() + sumAbandon, i);
                newX=new int[aNode.getX().length];
                System.arraycopy(aNode.getX(),0,newX,0,newX.length);
                newX[childNode.getThisStep()]=1;
                childNode.setX(newX);
                System.out.println(" "+aNode.getNumber()+" 生成孩子结点:"+childNode.getNumber()+" c="+childNode.getC()+" u="+childNode.getU()+" U="+U+" x="+Arrays.toString(childNode.getX()));
                //给孩子结点设置爸爸
                parent.add(aNode.getNumber());
                sumAbandon+=p[i];//舍弃掉的结点总花费
                if (isAAnswer(d,t,childNode.getX())&&childNode.getC() < U) {
                    //还有机会出现最优解
                    lifeNodes.add(childNode);
                    //尝试更新上界
                    if (childNode.getU() < U) {
                        U = childNode.getU();
                        ans = childNode.getNumber();
                    }
                }
                else
                {
                    System.out.println("未加入");
                }
            }
            lifeNodes.removeFirst();//移除自己
            lifeNodes.sort(new NodeComparator());//排序
            if (lifeNodes.isEmpty()||lifeNodes.getFirst().getC()>=U) {
                //说明此时完成遍历
                System.out.println("least cost=" + U);
                System.out.println("parent:"+Arrays.toString(parent.toArray()));
                System.out.print("顺序逆序为:");
                while (ans != -1) {
                    System.out.print(ans + " ");
                    ans = parent.get(ans);
                }
                return;
            }
            //执行到此处说明没有完成遍历,算法未结束
            aNode= lifeNodes.getFirst();//获取下一个结点,集合中无点也没问题,null
        }
    }
    boolean isAAnswer(int[]d,int[]t,int[]x)
    {

        class LittleNode implements Comparable<LittleNode>
        {
            int t;
            int d;

            public int getT() {
                return t;
            }

            public int getD() {
                return d;
            }

            public LittleNode(int t, int d) {
                this.t = t;
                this.d = d;
            }

            @Override
            public int compareTo(LittleNode cell) {
                if(this.d==cell.d&&this.t==cell.t)
                {
                    return 0;
                }
                else if(this.d>cell.d)
                {
                    return -1;
                }
                else
                {
                    return 1;
                }
            }
        }
        //将已选中的任务加入集合,集合自动排序
        TreeSet<LittleNode> nodes=new TreeSet<LittleNode>();
        int n=0;
        for(int i=0;i<x.length;i++)
        {
            if(x[i]!=0)
            {
                nodes.add(new LittleNode(t[i],d[i]));
            }
        }
        //开始遍历判断
        boolean flag=true;
        int ddl=nodes.first().getD();
        while (!nodes.isEmpty())
        {
            ddl=Math.min(ddl,nodes.first().getD());//ddl和当前ddl最晚的任务的ddl最小值
            if(ddl-nodes.first().getT()<0)
            {
                //时间不够了
                flag=false;
                break;
            }
            else
            {
                ddl=ddl-nodes.first().getT();//求最新ddl
                nodes.remove(nodes.first());//移除已做过的任务
            }

        }
        System.out.println(flag);
        return flag;
    }
}

//Node.java
public class Node implements Comparable<Node>{
    int number;//节点的序号
    int u;//上界
    int c;//下界
    int thisStep;//当前考虑的最后一个结点是第几个,根节点为-1,允许出现0
    int[]x;//当前结点的选择
    public Node(int number, int u, int c,int thisStep) {
        this.number = number;
        this.u = u;
        this.c = c;
        this.thisStep=thisStep;
    }

    public int getU() {
        return u;
    }

    public int getC() {
        return c;
    }

    public int getNumber() {
        return number;
    }

    public int[] getX() {
        return x;
    }

    public int getThisStep() {
        return thisStep;
    }

    public void setX(int[] x) {
        this.x = x;
    }

    @Override
    public int compareTo(Node node) {
        if(this.getC()==node.getC())//(this.getC()==node.getC()&&this.getU()==node.getU())
        {
            return 0;
        }
        else if(this.getC()<node.getC())
        {
            return -1;
        }
        else //(this.getC()>node.getC())
        {
            return 1;
        }
    }
}
//NodeComparator.java
import java.util.Comparator;

public class NodeComparator implements Comparator<Node> {

    @Override
    public int compare(Node node, Node t1) {
        if(node.getC()==t1.getC())
        {
            return 0;
        }
        else if(node.getC()<t1.getC())
        {
            return -1;
        }
        else //(this.getC()>node.getC())
        {
            return 1;
        }
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值