zoukankan      html  css  js  c++  java
  • 谨以此文纪念一周的心血历程

    在上一周完成的基础上,大家觉得这电梯是不是有点low啊,现在都智能化了,哪还有这么蠢的电梯啊,所以我们要让电梯的调度智能化,怎么个智能化呢?我们这里也只是简单的考虑以下捎带问题,所谓捎带,就是当我在电梯去往目的地的途中,按下一个可以在途中解决的按钮,那么这次请求就可以被捎带了,具体怎么说呢?主要以下说明:

    1. (e.sta = UP→10>=e.n>e.e_n) || (e.sta = DOWN1<=e.n<e.e_n)1 注释:本段所述的可捎带条件可以这样理解:①电梯状态向上运行时,发出向上请求的楼层处于当前楼层和10层之间;②电梯状态向下运行时,发出向下请求的楼层处于当前楼层和1层之间。
    2. 对于任意一个楼层请求r=(FR, n, dir, t),如果电梯当前是运动状态,则顺路捎带请求一定有: (r.dir=e.sta) && ((r.dir=UP(r.n <= e.n)&&(r.n>e.e_n)) || (r.dir=DOWN(r.n>=e.n)&&(r.n<e.e_n))) 注释:本段所述的可捎带条件可以这样理解:电梯状态向上或向下运行时,新楼层请求的运动方向与当前方向一致,而且新请求发生的楼层在当前所处楼层和目标楼层之间。
    3. 对于任意一个电梯内运行请求r=(ER,n,t),如果是电梯当前运动状态下的顺路捎带请求,则一定有: (e.sta=UP(10=>r.n > e.e_n)) || (e.sta=DOWN (1<=r.n<e.e_n)) 注释:本段所述的可捎带状态可以这样理解:电梯内请求的目标楼层在电梯的前进方向上
    4. 对于e.sta = STILL状态分为2种情况。一是在电梯处于停留状态(WFS状态),此种情况没有“顺路捎带”请求,因为此时请求队列为空;(注意STILL状态仅用于输出表达,输入只有UP/DOWN两个状态)
    5. 可捎带请求的条件是,该请求时非同质请求

    当时我看的时一脸懵逼啊,可谓是一点思路都没有。现在才发现,当老师也不容易啊,写完了讲不清…………

    待我慢慢道来,我们分为以下几步;

    如何解决捎带问题

    我们可以将捎带分为两类:

    1. 第一类,在电梯途中的电梯外的请求,该请求必须在电梯的当前楼层与目标楼层之间,且方向与电梯运动方向相同
    2. 第二类,电梯内的请求,这一类请求意味着只要请求在电梯当前楼层之外,并且方向与运动方向相同,都可以捎带

    那么如何捎带了,相信大家到这时思路都差不多了,构建捎带队列,而捎带队列的构建,小编我是想了整整一晚上啊,硬是没开始写代码。当时构建的方法主要有两种想法

    1. 按照时间构建捎带队列,将请求队列中符合稍带条件的请求按时间直接装入捎带队列,执行时按楼层执行,这样就不可避免的在执行的时候需要遍历一遍捎带队列,找出最接近的楼层捎带,更多的细节在于捎带请求完成后需要清空这一条捎带请求,需要将捎带队列改变,又会构成麻烦
    2. 按照楼层直接存储捎带队列,由于捎带有一个特点,那就是捎带会沿着电梯前进方向执行,举例来说,从一楼到十楼的过程中,被捎带的请求一定是从中间楼层,且方向向上的请求,或者电梯内请求。按照这种方式存储电梯也会带来麻烦,那就是同一楼层不止一条请求,且同一楼层的请求要按照输入的顺序输出,也就意味这在楼层中的请求也需要排序,不过相对于第一种,这个时间就不算什么了,所以我们在调度器中构建三维数组表示捎带请求队列

    这里给出上行途中电梯内请求的捎带的例子:

    if(this.request_n[k][0] > this.station[0] && this.pr_instr[0]>this.station[0] && this.request_n[k][2]==2 && this.request_n[k][4]==0) {
                        for(floor=this.station[0];floor < this.request_n[k][0];floor++) {
                            if(this.on_way[floor][0][0]!=0) {
                                arrive++;
                            }
                            arrive+=0.5;
                        }
                        //计算出从当前楼层到队列中一层的时间
                        if(this.occupy[(int) this.request_n[k][0]][1]!=0 && (arrive+this.stop_time)>this.request_n[k][1])  //表示该层楼电梯内的按钮已经被占用
                        {
                            this.request_n[k][4] = 1;
                            System.out.printf("#SAME");
                            output2(this.request_n[k]);
                        }
        /*import*/        else if((arrive+this.stop_time) > this.request_n[k][1]  && this.request_n[k][4]==0) { //判断时间问题,运行时有没有已经到达这一层
                            chose = 0;
                            while(this.on_way[(int) this.request_n[k][0]][chose][0]!=0) {   //表示按钮还没有被按,可以捎带,不是同质请求
                                chose++;
                            }
                            if(chose==1){    //如果改楼层有多条请求被捎带,按照输入顺序排好顺序
                                if((k+1)<this.on_way[(int) this.request_n[k][0]][0][4])
                                {
                                    temp = this.on_way[(int) this.request_n[k][0]][0];
                                    this.on_way[(int) this.request_n[k][0]][0] = this.request_n[k];
                                    this.on_way[(int) this.request_n[k][0]][chose] = temp;
                                }
                                else {
                                    this.on_way[(int) this.request_n[k][0]][chose] = this.request_n[k];//表示向上运行的电梯内请求捎带
                                }
                            }
                            else{
                                this.on_way[(int) this.request_n[k][0]][chose] = this.request_n[k];//表示向上运行的电梯内请求捎带
                            }
                            if(this.occupy[(int) this.request_n[k][0]][2]==0 || this.occupy[(int) this.request_n[k][0]][3]==0) {
                                j++;
                            }
                            this.occupy[(int) this.request_n[k][0]][1]=1;  //表示电梯内的按钮被按下
                            this.request_n[k][4] = k+1;  //表示该指令放入捎带队列中将被执行
    
                        }    
                    }
    主请求起到关键的作用

    主请求作为该次电梯执行的目标楼层,就是运行的最后一层,决定了电梯的运行方向,以及会捎带那些请求,在我们采用第二种方法后,每次执行的时整个请求队列,也就意味着,我们每次都将主请求执行结束,才意味着一次执行的结束,所以每次执行后都需要更新主请求,更新的主请求有两个来源,捎带队列中还未执行的请求,请求队列中还未执行的请求。主请求被确定后该请求就会被加入到捎带队列中,同时改楼层按钮被按下;代码实例如下

    if(this.station[1]==2){ //表示电梯之前是向下运行的,所以找出楼层最低的作为主请求
                    for(num=1;num<=10;) {
                        if(this.on_way[num][0][0]==0)
                            num++;
                        else 
                            break;
                    }  //判断捎带队列中的哪一个作为下一个主请求
                    if(num==11) {     //num==11.表示捎带队列已经空了,所以将请求队列中的下一个作为主请求,并加入到捎带队列中
                        while(this.request_n[i][4]!=0)
                            i++;  //表示在请求队列中将已经执行的队列过滤掉
                        this.on_way[0][0] = this.request_n[i];
                        this.pr_instr = this.request_n[i];
                        this.on_way[(int) this.request_n[i][0]][0] = this.request_n[i];//表示主请求的哪一个楼层的请求
                        
                        this.request_n[i][4] = i+1;
                    }
                    else {
                        this.on_way[0][0] = this.on_way[num][0];  //第0个表示主请求
                        this.pr_instr = this.on_way[num][0];
                    }
                }//如果是下行就找到最远的哪一个作为主请求,也就是楼层最小的那个作为朱请求
                //
                else if(this.station[1]==1){  //表示电梯之前是向上运行的
                    for(num=10;num>=1;) {
                        if(this.on_way[num][0][0]==0)
                            num--;
                        else 
                            break;
                    }  //判断捎带队列中的哪一个作为下一个主请求
                    if(num==0) {     //num==0.表示捎带队列已经空了,所以将请求队列中下一个作为主请求,并加入到捎带队列中
                        while(this.request_n[i][4]!=0)
                            i++;  //表示在请求队列中将已经执行的队列过滤掉
                        this.on_way[0][0] = this.request_n[i];
                        this.pr_instr = this.request_n[i];
                        this.on_way[(int) this.request_n[i][0]][0] = this.request_n[i];//表示主请求的哪一个楼层的请求
                        this.request_n[i][4] = i+1;
                    }
                    else {
                        this.on_way[0][0] = this.on_way[num][0];  //表示上行的时候将楼层最大的作为主请求
                        this.pr_instr= this.on_way[num][0];
                    }
                }
                //  ③,表示之前电梯是静止的
                else {
                    
                    while(this.request_n[i][4]!=0)
                        i++;  //表示在请求队列中将已经执行的队列过滤掉
                    this.on_way[0][0] = this.request_n[i];
                    this.pr_instr = this.request_n[i];
                    this.on_way[(int) this.request_n[i][0]][0] = this.request_n[i];//表示主请求的哪一个楼层的请求
                    
                    this.request_n[i][4] = i+1;
                }
                
                if(this.pr_instr[3]==1) {   //表示上行的
                    this.occupy[(int) this.pr_instr[0]][2]=1;
                }
                else if(this.pr_instr[3]==2) {   //表示下行
                    this.occupy[(int) this.pr_instr[0]][3]=1;
                }
                else if(this.pr_instr[2]==2) {   //表示在电梯内
                    this.occupy[(int) this.pr_instr[0]][1]=1;
                }
            }
     判断同质请求会很麻烦

    同质请求的判断稍不留神就出错了,小编也是打了好几次补丁才最终完成同质请求的判断,因为同质请求牵涉到的属性有点多;楼层,时间,请求队列,捎带队列这些都会影响到同质请求的判断,那么到底什么样的请求才算是同质请求呢?以及判断为什么会如此的麻烦呢?

    1. 同质请求意味着在请求到达目标楼层之前,对于目标楼层发出了多个相同请求,小编在室友的指导下,采用了他的方法,楼层的按钮。同一楼层只有三种按钮,当该楼层的按钮被按下以后,在该楼层的请求完成之前,按钮都处于按下的状态,也就意味着继续按同一按钮是没有意义的,所以这样来判断同质
    2. 关于同质牵涉到的时间问题是,电梯在运动过程中,途中电梯有捎带请求执行的时候,他需要执行捎带请求,所以时间会向后延长1s,所以在计算同质请求的时候,时间要计算到判断同质请求的那一楼层

    见代码:

    for(floor=this.station[0];floor < this.request_n[k][0];floor++) {
                            if(this.on_way[floor][0][0]!=0) {
                                arrive++;
                            }
                            arrive+=0.5;
                        }
                        //计算出从当前楼层到队列中一层的时间
                        if(this.occupy[(int) this.request_n[k][0]][1]!=0 && (arrive+this.stop_time)>this.request_n[k][1])  //表示该层楼电梯内的按钮已经被占用
                        {
                            this.request_n[k][4] = 1;
                            System.out.printf("#SAME");
                            output2(this.request_n[k]);    //在时间允许内,按钮已经被按下了,所以判断为同质请求
                        }

    如何解决请求时间与执行时间

     关于请求时间与执行时间的计算,有几点感觉需要注意,重要的是,时间与请求有关,还与主请求有关。对于当前时间,如果主请求时间晚于当前时间,那么电梯就要停止运行,等待主请求的到来,因为没有主请求,电梯是不会运行的。而电梯运行的途中,对于请求时间,需要计算从此次运行的开始时刻到达该楼层的时间。用来判断是否需要等待,如果需要等待,还需要在计算一次运行的时间,代码如下

    if(state_in[0]==move[0]) {
                            if(this.in_way[this.state_in[0]][0][1]>this.st_time) {
                                this.st_time = this.in_way[this.state_in[0]][0][1];
                            }
                            this.st_time = this.st_time + this.mo_time;
                        }
                        else {
                            this.st_time = this.st_time + this.mo_time;
                            if(this.in_way[this.state_in[0]][0][1]>this.st_time) {
                                this.st_time = this.in_way[this.state_in[0]][0][1];
                                this.st_time = this.st_time + this.mo_time;
                            }
                        }
                        this.mo_time = 0;   //判断是否是主指令

    总结

    对于本题我的类图如下:

    小小收获

    对于本课程收获,前三周虽然过的十分十分的辛苦,但是收获还是有的。感觉从来没有de过这么久的bug,没有写过这么久的bug,没有从头速成写代码。这些都是第一次。还有就是在计组课程之上对于设计理解了更多。关于设计思路,方法等,所以一般会在写代码之前写readme。对于整体的设计还是要更加的注重细节的处理,多在细节上花功夫,会使debug的过程简单很多。另一方面,互测虽然不是很“友好”,但是在看别人的代码中,收获了很多,代码的风格,处理问题的方式,等等。

     

     

  • 相关阅读:
    tensorflow 2.0 学习 (十) 拟合与过拟合问题
    tensorflow 2.0 学习 (九) tensorboard可视化功能认识
    tensorflow 2.0 学习 (八) keras模块的认识
    tensorflow 2.0 学习 (七) 反向传播代码逐步实现
    tensorflow 2.0 学习 (六) Himmelblua函数求极值
    tensorflow 2.0 学习 (五)MPG全连接网络训练与测试
    arp协议简单介绍
    Pthread spinlock自旋锁
    线程和进程状态
    内核态(内核空间)和用户态(用户空间)的区别和联系·
  • 原文地址:https://www.cnblogs.com/wevolf/p/8683201.html
Copyright © 2011-2022 走看看