• 谨以此文纪念一周的心血历程


    在上一周完成的基础上,大家觉得这电梯是不是有点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的过程简单很多。另一方面,互测虽然不是很“友好”,但是在看别人的代码中,收获了很多,代码的风格,处理问题的方式,等等。

     

     

  • 相关阅读:
    JS 使用 html2canvas 将页面转PDF
    代码记录
    js 原生图片批量上传 multiple="multiple"
    Go中的HTTP debug技能
    位运算 交换2个数 异或运算
    记一次 JMeter 压测 HTTPS 性能问题 拂衣 阿里云云栖号 20220527 19:00 发表于北京
    RVA relative virtual address PE
    进制
    浏览器是不允许页面直接读取本地硬盘资源的
    四平方和定理
  • 原文地址:https://www.cnblogs.com/wevolf/p/8683201.html
Copyright © 2020-2023  润新知