第二次博客作业

uml图

流程控制

线程配合

主要线程 功能
InputThread 获取输入线程:获取输入的电梯请求和乘客请求,并分别存储到ElevatorRequestList与PersonRequestList中。
ElevatorAddThread 电梯增加线程:提取ElevatorReuqestList中的电梯请求,并在系统中添加相应的电梯。
MainControlThread 主控线程:提取PersonRequestList中的乘客请求,并生成对应的TaskChainThread线程(以下简称tct线程)来管理每一个请求对应的电梯运行。
TaskChainThreadPoolThread 线程池线程:管理所有tct线程。在所有的tct线程执行完任务后,关闭所有电梯线程。
Main 主线程:程序运行线程。

运行线程

线程类名称 功能
VerticalElevator 纵向电梯:负责处理接收到的纵向任务。
CircularElevator 环形电梯:负责处理接收到的横向任务。
TaskChainThread 任务链:存储任务链,并根据每一个任务的完成情况,将相应任务依次分配给相应电梯。

电梯分配策略

静态分配

设计好两个类,分别是VerticalElevatorMap(以下简称VEM)与CircularElevatorMap(以下简称CEM),分别存储纵向电梯与横向电梯队列。MainControlThread(主控线程)将任务拆解为任务链,将其中的纵向任务分发送给VEM,获得已存在电梯中最优电梯;同理,获得CEM中的最优电梯。

初始化

private static void init() {
    TimableOutput.initStartTimestamp();

    ElevatorRequestList elevatorRequestList = new ElevatorRequestList();
    PersonRequestList personRequestList = new PersonRequestList();

    /*输入线程*/
    new InputThread(personRequestList, elevatorRequestList).start();

    VerticalElevatorMap verticalElevatorMap = new VerticalElevatorMap();
    CircularElevatorMap circularElevatorMap = new CircularElevatorMap();

    /*线程池线程*/
    TaskChainThreadPoolThread tctpThread = new TaskChainThreadPoolThread(
            verticalElevatorMap, circularElevatorMap);
    tctpThread.start();

    MainControlThread mainControlThread = new MainControlThread(
            personRequestList, verticalElevatorMap, circularElevatorMap, tctpThread);
    /*电梯主控线程*/
    mainControlThread.start();

    ElevatorAddThread elevatorAddThread = new ElevatorAddThread(
            elevatorRequestList, verticalElevatorMap, circularElevatorMap);
    /*电梯增加线程*/
    elevatorAddThread.start();
	
    /*初始电梯设置*/
    VerticalElevatorTable verticalElevatorTableA = new VerticalElevatorTable(Building.A, 1, 8);
    VerticalElevator verticalElevatorA = new VerticalElevator(
            Building.A, 1, verticalElevatorTableA, 0.6);
    verticalElevatorMap.add(verticalElevatorA);
    new Thread(verticalElevatorA).start();
    VerticalElevatorTable verticalElevatorTableB = new VerticalElevatorTable(Building.B, 2, 8);
    VerticalElevator verticalElevatorB = new VerticalElevator(
            Building.B, 2, verticalElevatorTableB, 0.6);
    verticalElevatorMap.add(verticalElevatorB);
    new Thread(verticalElevatorB).start();
    VerticalElevatorTable verticalElevatorTableC = new VerticalElevatorTable(Building.C, 3, 8);
    VerticalElevator verticalElevatorC = new VerticalElevator(
            Building.C, 3, verticalElevatorTableC, 0.6);
    verticalElevatorMap.add(verticalElevatorC);
    new Thread(verticalElevatorC).start();
    VerticalElevatorTable verticalElevatorTableD = new VerticalElevatorTable(Building.D, 4, 8);
    VerticalElevator verticalElevatorD = new VerticalElevator(
            Building.D, 4, verticalElevatorTableD, 0.6);
    verticalElevatorMap.add(verticalElevatorD);
    new Thread(verticalElevatorD).start();
    VerticalElevatorTable verticalElevatorTableE = new VerticalElevatorTable(Building.E, 5, 8);
    VerticalElevator verticalElevatorE = new VerticalElevator(
            Building.E, 5, verticalElevatorTableE, 0.6);
    verticalElevatorMap.add(verticalElevatorE);
    new Thread(verticalElevatorE).start();

    CircularElevatorTable circularElevatorTable = new CircularElevatorTable(1, 6, 8, 31);
    CircularElevator circularElevator = new CircularElevator(1, 6, circularElevatorTable, 0.6);
    circularElevatorMap.add(circularElevator);
    new Thread(circularElevator).start();

}

代码分析

InputThread

分别将电梯请求与乘客请求放入elevatorRequestList与personRequestList中。注意设置相应list的setEnd()的方法。

private void work() {
    ElevatorInput elevatorInput = new ElevatorInput(System.in);
    while (true) {
        Request request = elevatorInput.nextRequest();

        if (null == request) {
            personRequestList.setEnd();
            elevatorRequestList.setEnd();
            return;
        } else {
            if (request instanceof PersonRequest) {
                personRequestList.add((PersonRequest) request);
            } else if (request instanceof ElevatorRequest) {
                elevatorRequestList.add((ElevatorRequest) request);
            }
        }
    }
}

ElevatorRequestList, PersonRequestList

本质上是线程安全的List,将add()方法与take()方法注意上锁。其中take()方法如下:

public synchronized ElevatorRequest take() throws InterruptedException {
    if (elevatorRequests.isEmpty()) {
        wait();
    }
    if (elevatorRequests.isEmpty()) {
        return null;
    }

    return this.elevatorRequests.take();
}

第一个isEmpty()代码块,由add()方法唤醒;第二个isEmpty()代码块,由setEnd()方法唤醒。

ElevatorTable

每一个Elevator都会分配一个自己的ElevatorTable,负责控制该电梯的状态。以VerticalElevatorTable为例。

将乘客需求拆分为TaskIn(进入电梯任务)TaskOut(离开电梯任务),分别用两个队列存储,只有该乘客需求的TaskIn任务执行完之后,才能执行该乘客的TaskOut任务。若达到存储容量,则不能向ElevatorTable存放请求(wait()),直到某一个TaskOut任务执行完,表示一个乘客出电梯,则才可继续向ElevatorTable存放请求。

电梯每运行一层,都会判断ElevatorTable是否更新,然后指导该电梯下一步是向上还是向下。

每到达一个楼层,都会判断该楼层是否有相应的TaskIn和可执行的TaskOut任务,然后执行。

VerticalElevatorMap, CircularElevatorMap

VEM以座为键,存放该座所有的<VE, VET>;CEM以楼层为键,存放该楼层所有的<CE, CET>。最为核心的的方法是getProperElevatorTable()。

VEM的getProperElevatorTable(),本身策略很简单,即排着分配给该座的纵向电梯,即平均调度策略。通过一个循环迭代器来实现。

public synchronized VerticalElevatorTable getProperElevatorTable(
        Building staticBuilding) throws Exception {
    while (map.isEmpty()) {
        wait();
    }

    Iterator<VerticalElevatorTable> iterator = iteratorMap.get(staticBuilding);

    if (!iterator.hasNext()) {
        iterator = map.get(staticBuilding).values().iterator();
        iteratorMap.put(staticBuilding, iterator);
    }
    return iterator.next();
}

CEM的getProperElevatorTable()方法稍微复杂一下。才用只处理一次换乘,若满足

1. 小于等于1次换乘即可到达目标楼座。
1. 纵向上下楼层少于**前往一层**。

则才用该换乘策略,代码如下:

public synchronized CircularElevatorTable getProperElevatorTable(
        Integer targetFloor, Building fromBuilding, Building toBuilding) throws Exception {
    while (map.isEmpty()) {
        wait();
    }

    List<CircularElevatorTable> list = new ArrayList<>();
    for (Map<CircularElevator, CircularElevatorTable> cetMap : map.values()) {
        for (CircularElevatorTable elevatorTable : cetMap.values()) {
            if (elevatorTable.canReach(fromBuilding) && elevatorTable.canReach(toBuilding)) {
                list.add(elevatorTable);
            }
        }
    }

    CircularElevatorTable chosenEt = null;
    int distance = 100;
    for (CircularElevatorTable elevatorTable : list) {
        if (Math.abs(elevatorTable.getStaticFloor() - targetFloor) < distance) {
            distance = Math.abs(elevatorTable.getStaticFloor() - targetFloor);
            chosenEt = elevatorTable;
        }
    }

    if (null == chosenEt) {
        throw new Exception("Chosen Et is NULL!");
    }
    return chosenEt;
}

ElevatorAddThread

主要任务为两个:

1. start相应添加的电梯线程
1. 将相应的Elevator与ElevatorTable存储在VerticalElevatorList与CircularElevatorList中。

核心代码如下:

private void work() throws Exception {
    while (true) {
        if (elevatorRequestList.isEnd() && elevatorRequestList.isEmpty()) {
            return;
        }

        ElevatorRequest request = elevatorRequestList.take();
        if (null == request) {
            continue;
        }
        int elevatorId = request.getElevatorId();
        String type = request.getType();
        Building building = Building.analyseChar(request.getBuilding());
        int floor = request.getFloor();
        int capacity = request.getCapacity();
        double speed = request.getSpeed();
        int switchInfo = request.getSwitchInfo();

        if (type.equals("building")) {
            VerticalElevator elevator = new VerticalElevator(building, elevatorId,
                    new VerticalElevatorTable(building, elevatorId, capacity), speed);
            new Thread(elevator).start();
            verticalElevatorMap.add(elevator);
        } else {
            CircularElevator elevator = new CircularElevator(floor, elevatorId,
                    new CircularElevatorTable(floor, elevatorId, capacity, switchInfo), speed);
            new Thread(elevator).start();
            circularElevatorMap.add(elevator);
        }
    }
}

MainControlThread

主要任务如下:

1. 提取乘客需求,并将需求拆解为**任务队列**。
1. 将每一个任务都分配给一个*适当*的电梯
1. 创建TaskChainThread(任务链线程,以下简称tct线程)来执行**任务队列**。
1. 将tct放入tctPool中。

核心方法为creatTaskChainThread(),代码如下:

private synchronized void createTaskChainThread(int id,
                                                PersonRequest request) throws Exception {
    int fromFloor = request.getFromFloor();
    int toFloor = request.getToFloor();
    Building fromBuilding = Building.analyseChar(request.getFromBuilding());
    Building toBuilding = Building.analyseChar(request.getToBuilding());
    int personId = request.getPersonId();

    Queue<TaskNode> queue = new LinkedList<>();

    if (fromBuilding.equals(toBuilding)) {
        queue.add(new TaskNode(new VerticalRequest(personId, fromFloor, toFloor),
                verticalElevatorMap.getProperElevatorTable(fromBuilding)));
    } else {
        int targetFloor = (fromFloor + toFloor) / 2;    //在精度上问题不大
        int transferFloor = circularElevatorMap.getProperElevatorFloor(
                targetFloor, fromBuilding, toBuilding);
        if (fromFloor != transferFloor) {
            queue.add(new TaskNode(new VerticalRequest(personId, fromFloor, transferFloor),
                    verticalElevatorMap.getProperElevatorTable(fromBuilding)));
        }
        queue.add(new TaskNode(new CircularRequest(personId, fromBuilding, toBuilding),
                circularElevatorMap.getProperElevatorTable(
                        targetFloor, fromBuilding, toBuilding)));
        if (transferFloor != toFloor) {
            queue.add(new TaskNode(new VerticalRequest(personId, transferFloor, toFloor),
                    verticalElevatorMap.getProperElevatorTable(toBuilding)));
        }
    }

    TaskChainThread taskChainThread = new TaskChainThread(id, queue, tctpThread);
    tctpThread.add(taskChainThread);

    taskChainThread.start();
}

TaskChainPoolThread

主要任务负责管理整个程序结束:在所有tct线程结束前,所有电梯都保持运行

程序缺点分析

最根本的问题,来自于只能静态分配电梯,而不能实时将请求分配给新加入的电梯。

导致强测很多测试点,RTLE,就是有的电梯很忙,有的电梯空闲。

后期,可以加入任务回溯模块。每个电梯任务在执行之前,在重新考虑一下是否分配合理。

度量分析

Method metrics

method CogC ev(G) iv(G) v(G)
com.company.VerticalRequest.VerticalRequest(int, int, int) 0.0 1.0 1.0 1.0
com.company.VerticalRequest.getId() 0.0 1.0 1.0 1.0
com.company.VerticalRequest.addToElevatorTable(ElevatorTable) 2.0 2.0 2.0 2.0
com.company.VerticalElevatorTable.VerticalElevatorTable(Building, Integer, Integer) 0.0 1.0 1.0 1.0
com.company.VerticalElevatorTable.setEnd() 0.0 1.0 1.0 1.0
com.company.VerticalElevatorTable.isEnd() 0.0 1.0 1.0 1.0
com.company.VerticalElevatorTable.isEmpty() 0.0 1.0 1.0 1.0
com.company.VerticalElevatorTable.hasNoCapacity() 2.0 2.0 1.0 3.0
com.company.VerticalElevatorTable.getTask(int) 4.0 3.0 3.0 4.0
com.company.VerticalElevatorTable.finishTask(int) 7.0 2.0 4.0 4.0
com.company.VerticalElevatorTable.changeExecutable(int) 7.0 1.0 4.0 4.0
com.company.VerticalElevatorTable.binarySearch(int) 13.0 7.0 6.0 11.0
com.company.VerticalElevatorTable.addTask(TaskNode) 0.0 1.0 1.0 1.0
com.company.VerticalElevatorTable.addTask(int, int, TaskOut) 2.0 1.0 2.0 2.0
com.company.VerticalElevatorTable.addTask(int, int, TaskIn) 3.0 1.0 3.0 3.0
com.company.VerticalElevatorMap.setAllElevatorTableEnd() 3.0 1.0 3.0 3.0
com.company.VerticalElevatorMap.isEmpty() 0.0 1.0 1.0 1.0
com.company.VerticalElevatorMap.getProperElevatorTable(Building) 2.0 1.0 3.0 3.0
com.company.VerticalElevatorMap.add(VerticalElevator) 2.0 1.0 2.0 2.0
com.company.VerticalElevator.work() 11.0 4.0 5.0 7.0
com.company.VerticalElevator.VerticalElevator(Building, int, VerticalElevatorTable, double) 0.0 1.0 1.0 1.0
com.company.VerticalElevator.run() 1.0 1.0 2.0 2.0
com.company.VerticalElevator.open() 0.0 1.0 1.0 1.0
com.company.VerticalElevator.move(int) 2.0 1.0 1.0 2.0
com.company.VerticalElevator.hashCode() 0.0 1.0 1.0 1.0
com.company.VerticalElevator.getVerticalElevatorTable() 0.0 1.0 1.0 1.0
com.company.VerticalElevator.getStaticBuilding() 0.0 1.0 1.0 1.0
com.company.VerticalElevator.getId() 0.0 1.0 1.0 1.0
com.company.VerticalElevator.executeTask() 0.0 1.0 1.0 1.0
com.company.VerticalElevator.equals(Object) 2.0 3.0 1.0 3.0
com.company.VerticalElevator.close() 0.0 1.0 1.0 1.0
com.company.VerticalElevator.arrive() 0.0 1.0 1.0 1.0
com.company.TaskOut.executeTask(int, Building, int, int) 0.0 1.0 1.0 1.0
com.company.TaskNode.TaskNode(ExecutableRequest, ElevatorTable) 0.0 1.0 1.0 1.0
com.company.TaskNode.setFinished() 0.0 1.0 1.0 1.0
com.company.TaskNode.isFinished() 1.0 1.0 2.0 2.0
com.company.TaskNode.getId() 0.0 1.0 1.0 1.0
com.company.TaskNode.getElevatorTable() 0.0 1.0 1.0 1.0
com.company.TaskNode.addTaskToElevatorTable() 0.0 1.0 1.0 1.0
com.company.TaskIn.executeTask(int, Building, int, int) 0.0 1.0 1.0 1.0
com.company.TaskChainThreadPoolThread.work() 5.0 3.0 4.0 4.0
com.company.TaskChainThreadPoolThread.TaskChainThreadPoolThread(VerticalElevatorMap, CircularElevatorMap) 0.0 1.0 1.0 1.0
com.company.TaskChainThreadPoolThread.setEnd() 0.0 1.0 1.0 1.0
com.company.TaskChainThreadPoolThread.setAllElevatorTableEnd() 0.0 1.0 1.0 1.0
com.company.TaskChainThreadPoolThread.run() 1.0 1.0 2.0 2.0
com.company.TaskChainThreadPoolThread.isEnd() 0.0 1.0 1.0 1.0
com.company.TaskChainThreadPoolThread.isEmpty() 0.0 1.0 1.0 1.0
com.company.TaskChainThreadPoolThread.finish(TaskChainThread) 1.0 2.0 1.0 2.0
com.company.TaskChainThreadPoolThread.add(TaskChainThread) 0.0 1.0 1.0 1.0
com.company.TaskChainThread.work() 7.0 4.0 4.0 4.0
com.company.TaskChainThread.TaskChainThread(int, Queue, TaskChainThreadPoolThread) 0.0 1.0 1.0 1.0
com.company.TaskChainThread.run() 1.0 1.0 2.0 2.0
com.company.TaskChainThread.equals(Object) 1.0 1.0 1.0 2.0
com.company.TaskChainThread.addTask(TaskNode) 0.0 1.0 1.0 1.0
com.company.PersonRequestList.take() 2.0 2.0 2.0 3.0
com.company.PersonRequestList.setEnd() 0.0 1.0 1.0 1.0
com.company.PersonRequestList.isEnd() 0.0 1.0 1.0 1.0
com.company.PersonRequestList.isEmpty() 0.0 1.0 1.0 1.0
com.company.PersonRequestList.add(PersonRequest) 0.0 1.0 1.0 1.0
com.company.OutputClass.println(String) 0.0 1.0 1.0 1.0
com.company.MainControlThread.work() 6.0 4.0 4.0 5.0
com.company.MainControlThread.run() 1.0 1.0 2.0 2.0
com.company.MainControlThread.MainControlThread(PersonRequestList, VerticalElevatorMap, CircularElevatorMap, TaskChainThreadPoolThread) 0.0 1.0 1.0 1.0
com.company.MainControlThread.createTaskChainThread(int, PersonRequest) 6.0 1.0 4.0 4.0
com.company.Main.main(String[]) 0.0 1.0 1.0 1.0
com.company.Main.init() 0.0 1.0 1.0 1.0
com.company.InputThread.work() 8.0 3.0 5.0 5.0
com.company.InputThread.run() 0.0 1.0 1.0 1.0
com.company.InputThread.InputThread(PersonRequestList, ElevatorRequestList) 0.0 1.0 1.0 1.0
com.company.ElevatorRequestList.take() 2.0 2.0 2.0 3.0
com.company.ElevatorRequestList.setEnd() 0.0 1.0 1.0 1.0
com.company.ElevatorRequestList.isEnd() 0.0 1.0 1.0 1.0
com.company.ElevatorRequestList.isEmpty() 0.0 1.0 1.0 1.0
com.company.ElevatorRequestList.add(ElevatorRequest) 0.0 1.0 1.0 1.0
com.company.ElevatorAddThread.work() 9.0 4.0 4.0 6.0
com.company.ElevatorAddThread.run() 1.0 1.0 2.0 2.0
com.company.ElevatorAddThread.ElevatorAddThread(ElevatorRequestList, VerticalElevatorMap, CircularElevatorMap) 0.0 1.0 1.0 1.0
com.company.CircularRequest.getId() 0.0 1.0 1.0 1.0
com.company.CircularRequest.CircularRequest(int, Building, Building) 0.0 1.0 1.0 1.0
com.company.CircularRequest.addToElevatorTable(ElevatorTable) 2.0 2.0 2.0 2.0
com.company.CircularElevatorTable.setEnd() 0.0 1.0 1.0 1.0
com.company.CircularElevatorTable.nearestSearch(Building) 31.0 26.0 21.0 26.0
com.company.CircularElevatorTable.isEnd() 0.0 1.0 1.0 1.0
com.company.CircularElevatorTable.isEmpty() 0.0 1.0 1.0 1.0
com.company.CircularElevatorTable.hasNoCapacity() 2.0 2.0 1.0 3.0
com.company.CircularElevatorTable.hashCode() 0.0 1.0 1.0 1.0
com.company.CircularElevatorTable.getTask(Building) 4.0 3.0 3.0 4.0
com.company.CircularElevatorTable.getStaticFloor() 0.0 1.0 1.0 1.0
com.company.CircularElevatorTable.finishTask(Building) 7.0 2.0 4.0 4.0
com.company.CircularElevatorTable.equals(Object) 2.0 3.0 1.0 3.0
com.company.CircularElevatorTable.CircularElevatorTable(Integer, Integer, Integer, Integer) 3.0 1.0 3.0 3.0
com.company.CircularElevatorTable.changeExecutable(int) 7.0 1.0 4.0 4.0
com.company.CircularElevatorTable.canReach(Building) 0.0 1.0 1.0 1.0
com.company.CircularElevatorTable.addTask(TaskNode) 0.0 1.0 1.0 1.0
com.company.CircularElevatorTable.addTask(int, Building, TaskOut) 2.0 1.0 2.0 2.0
com.company.CircularElevatorTable.addTask(int, Building, TaskIn) 3.0 1.0 3.0 3.0
com.company.CircularElevatorMap.setAllElevatorTableEnd() 3.0 1.0 3.0 3.0
com.company.CircularElevatorMap.isEmpty() 0.0 1.0 1.0 1.0
com.company.CircularElevatorMap.getProperElevatorTable(Integer, Building, Building) 12.0 2.0 8.0 9.0
com.company.CircularElevatorMap.getProperElevatorFloor(Integer, Building, Building) 0.0 1.0 1.0 1.0
com.company.CircularElevatorMap.add(CircularElevator) 2.0 1.0 2.0 2.0
com.company.CircularElevator.work() 11.0 4.0 5.0 7.0
com.company.CircularElevator.run() 1.0 1.0 2.0 2.0
com.company.CircularElevator.open() 0.0 1.0 1.0 1.0
com.company.CircularElevator.move(Building) 0.0 1.0 1.0 1.0
com.company.CircularElevator.hashCode() 0.0 1.0 1.0 1.0
com.company.CircularElevator.getStaticFloor() 0.0 1.0 1.0 1.0
com.company.CircularElevator.getId() 0.0 1.0 1.0 1.0
com.company.CircularElevator.getCircularElevatorTable() 0.0 1.0 1.0 1.0
com.company.CircularElevator.executeTask() 0.0 1.0 1.0 1.0
com.company.CircularElevator.equals(Object) 2.0 3.0 1.0 3.0
com.company.CircularElevator.close() 0.0 1.0 1.0 1.0
com.company.CircularElevator.CircularElevator(Integer, int, CircularElevatorTable, double) 0.0 1.0 1.0 1.0
com.company.CircularElevator.arrive() 0.0 1.0 1.0 1.0
com.company.Building.getValue() 0.0 1.0 1.0 1.0
com.company.Building.getNextBuilding(Building, Building) 11.0 21.0 1.0 21.0
com.company.Building.Building(int) 0.0 1.0 1.0 1.0
com.company.Building.analyseChar(char) 1.0 6.0 1.0 6.0
Total 221.0 213.0 220.0 280.0
Average 1.8728813559322033 1.805084745762712 1.8644067796610169 2.3728813559322033

总的来说,涉及到环形电梯运行的方法,就会复杂度很高。比如说:CircularElevatorTable的nearestSearch()方法

private Building nearestSearch(Building currentBuilding) throws Exception {
    switch (currentBuilding) {
        case A: { if (executableMap.containsKey(Building.B)) {
                return Building.B;
            } else if (executableMap.containsKey(Building.E)) {
                return Building.E;
            } else if (executableMap.containsKey(Building.C)) {
                return Building.C;
            } else if (executableMap.containsKey(Building.D)) {
                return Building.D;
            } else {
                throw new Exception("This Building DOESN'T Exist!");
            }
        } case B: { if (executableMap.containsKey(Building.C)) {
                return Building.C;
            } else if (executableMap.containsKey(Building.A)) {
                return Building.A;
            } else if (executableMap.containsKey(Building.D)) {
                return Building.D;
            } else if (executableMap.containsKey(Building.E)) {
                return Building.E;
            } else {
                throw new Exception("This Building DOESN'T Exist!");
            }
        } case C: { if (executableMap.containsKey(Building.D)) {
                return Building.D;
            } else if (executableMap.containsKey(Building.B)) {
                return Building.B;
            } else if (executableMap.containsKey(Building.E)) {
                return Building.E;
            } else if (executableMap.containsKey(Building.A)) {
                return Building.A;
            } else {
                throw new Exception("This Building DOESN'T Exist!");
            }
        } case D: { if (executableMap.containsKey(Building.E)) {
                return Building.E;
            } else if (executableMap.containsKey(Building.C)) {
                return Building.C;
            } else if (executableMap.containsKey(Building.A)) {
                return Building.A;
            } else if (executableMap.containsKey(Building.B)) {
                return Building.B;
            } else {
                throw new Exception("This Building DOESN'T Exist!");
            }
        } case E: { if (executableMap.containsKey(Building.A)) {
                return Building.A;
            } else if (executableMap.containsKey(Building.D)) {
                return Building.D;
            } else if (executableMap.containsKey(Building.B)) {
                return Building.B;
            } else if (executableMap.containsKey(Building.C)) {
                return Building.C;
            } else {
                throw new Exception("This Building DOESN'T Exist!");
            }
        } default:
    } throw new Exception("Exceptions with Building Select!");
}

通过暴力枚举五个楼座之间的关系,从而确保最短路径选择,导致了很难看的复杂度情况。

posted on 2022-04-30 15:06  BuniQ  阅读(37)  评论(0编辑  收藏  举报