你不优化,我不优化,那大家就都是满分啦


(一)写在最前

  电梯问题由于和实际关联比较紧密,所以实际上可以操作的空间比较多。

  但第二单元的电梯,需要实现捎带;第三单元的电梯,需要实现楼层限制、人数限制、三电梯,限制了可以优化的范围,所以这里仅仅做一些自己在写电梯时候的小思考。

(二)第二次电梯

  经过查阅资料,可以得知比较常见的电梯调度算法包括FCFS、SSTF、SCAN等,其中比较容易书写,且可以保证性能不是很差的是SCAN电梯。但是查阅资料可以发现,SCAN电梯是需要反复扫描楼层,来检测是否有人员可以搭乘电梯,这就带来了一个问题,可能刚刚经过的楼层恰好来了个请求,且运动方向上并没有新的请求,原始的SCAN电梯会选择 一条道跑到黑,这里是有一些可以改进的空间的。

  可以通过判断当前电梯运动方向上是否有新的请求在等待,如果没有,则折返(这里在书写的时候容易把代码写成带有上下优先级的做法,导致电梯反复运动,所以这里放上我的代码)

    private void detect() {
if (arr.isEmpty()) {
upordown = 0;
}
if (upordown == 0 || upordown == 1) {
for (Person p : arr) {
if (p.getfrom() > nowfloor &&
p.getstatus() == 0 && passanger < max) {
upordown = 1;
break;
} else if (p.getto() > nowfloor && p.getstatus() == 1) {
upordown = 1;
break;
} else {
upordown = 0;
}
}
}
if (upordown == 0 || upordown == -1) {
for (Person p : arr) {
if (p.getfrom() < nowfloor &&
p.getstatus() == 0 && passanger < max) {
upordown = -1;
break;
} else if (p.getto() < nowfloor && p.getstatus() == 1) {
upordown = -1;
break;
} else {
upordown = 0;
}
}
}
}

  这段代码通过一个标记位来检测电梯是否需要折返,1代表上行,0代表停止,-1代表下行。之前说过的有上下优先级是因为在判断条件中未加入当前运行方向的判断。至此,SCAN电梯就进化成了所谓的LOOK电梯。

  事实上,通过检测电梯当前楼层上下分别有多少请求,可以通过请求的数量来判断向哪一方向运动更优,这里仅需要设立两个数量记录位即可,为了保证可能到来的新请求对判断造成影响,上下方向请求数量若小于某个临界值,则并不需要改变电梯运动方向,以此来做优化。

  看到某位神仙通过写了好几个电梯同时跑,然后输出一个buffer存的字符串数组,也是觉得十分神奇了,不过,用了一些数据测试这位大神的电梯,与我写的这个单LOOK电梯(优化后),并没有发现他的方法有明显的优势,有的点我比他慢,有的点他比我慢,不过可能是因为测试数据数量比较少,这里仅作记录,膜拜一下多电梯大佬。

(三)第三次电梯

  由于第二次电梯不限载客数量,不需要考虑换乘等,所以导致需要优化的点其实很少,所以这里重点讨论一下第三次电梯。

  第三次电梯有三个限制,一是人数限制,二是楼层限制,三是三个电梯。这里仅对人数限制和楼层限制做讨论。

  人数限制导致了之前缩写的LOOK优化电梯在捎带的时候性能并不是很好,而最简单的调度器使用是通过直接分发到ABC三个电梯中,让电梯去运送用户,这里就导致了优先级的产生,会让某个电梯负载过重,而在请求队列中阻塞许多用户,而另外两个电梯甚至可能没有请求,这里可以通过对每个请求使用if去判断,是否可以通过电梯直达,若可以,则记录可以的电梯数目,通过一个随机数对此数目取余得到放请求的电梯,这样随机分布对于第三次强测中纯随机数据很有效,实现也很简单,这里不再赘述。

  之后是楼层限制,这一点拖慢电梯的主要原因是换乘,我们需要通过选择某个电梯将乘客请求送到某个楼层,再由另外的电梯去运送,而每个电梯的运送速度是不一样的,所以在考虑分发乘客请求的时候,我对时间片进行了考量,代码如下:

        int[] flag = {0, 0, 0, 0, 0, 0};
double[] min = {200, 200, 200, 200, 200, 200};
int [] n = {1, 1, 1, 1, 1, 1};
int i;
double t = 200;
int j = 0;
if (change == 1) {
if (elevator1[this.from + 3] == 1 && elevator2[this.to + 3] == 1) {
flag[0] = 1;
}
else if (elevator1[this.to + 3] == 1 && elevator2[this.from + 3] == 1) {
flag[1] = 1;
}
else if (elevator1[this.from + 3] == 1 && elevator3[this.to + 3] == 1) {
flag[2] = 1;
}
else if (elevator1[this.to + 3] == 1 && elevator3[this.from + 3] == 1) {
flag[3] = 1;
}
else if (elevator3[this.from + 3] == 1 && elevator2[this.to + 3] == 1) {
flag[4] = 1;
}
else if (elevator3[this.to + 3] == 1 && elevator2[this.from + 3] == 1) {
flag[5] = 1;
}
for (i = 0; i < 24; i++){
if ((Math.abs(i - 3 - this.from) * 0.4 + Math.abs(i - 3 - this.to) * 0.6 < min[2]) && ac[i] == 1) {
min[2] = Math.abs(i - 3 - this.from) * 0.4 + Math.abs(i - 3 - this.to) * 0.6;
n[2] = i - 3;
}
if ((Math.abs(i - 3 - this.to) * 0.4 + Math.abs(i - 3 - this.from) * 0.6 < min[3]) && ac[i] == 1) {
min[3] = Math.abs(i - 3 - this.to) * 0.4 + Math.abs(i - 3 - this.from) * 0.6;
n[3] = i - 3;
}
if ((Math.abs(i - 3 - this.from) * 0.4 + Math.abs(i - 3 - this.to) * 0.5 < min[0]) && ab[i] == 1) {
min[0] = Math.abs(i - 3 - this.from) * 0.4 + Math.abs(i - 3 - this.to) * 0.5;
n[0] = i - 3;
}
if ((Math.abs(i - 3 - this.to) * 0.4 + Math.abs(i - 3 - this.from) * 0.5 < min[1]) && ab[i] == 1) {
min[1] = Math.abs(i - 3 - this.to) * 0.4 + Math.abs(i - 3 - this.from) * 0.5;
n[1] = i - 3;
}
if ((Math.abs(i - 3 - this.from) * 0.5 + Math.abs(i - 3 - this.to) * 0.6 < min[4]) && bc[i] == 1) {
min[4] = Math.abs(i - 3 - this.from) * 0.5 + Math.abs(i - 3 - this.to) * 0.6;
n[4] = i - 3;
}
if ((Math.abs(i - 3 - this.to) * 0.5 + Math.abs(i - 3 - this.from) * 0.6 < min[5]) && bc[i] == 1) {
min[5] = Math.abs(i - 3 - this.to) * 0.5 + Math.abs(i - 3 - this.from) * 0.6;
n[5] = i - 3;
}
}
for (i = 0; i < 6; i++) {
if (flag[i] != 1) {
min[i] = 200;
}
} for (i = 0; i < 6; i++) {
if (t > min[i]) {
t = min[i];
j = i;
}
}
this.to = n[j];
}

  大致思路是记录电梯两两重叠的楼层,之后可以把乘客通过from和to与ABC电梯组合,分成六种情况,通过考量乘客在某种组合下所需要运动的总时间来决定拆分请求应该放在哪个电梯中,以此来求得比较优化的换乘方式,而非直接无脑将乘客送到1楼或者15楼,留下电梯日门。

  事实上,由于电梯换乘的开关门时间比较大,如果乘客能够直达,便最好不需要换乘。当然,这里由于电梯运动的因素,还可以考量三电梯换乘,不过这里需要记录电梯当前乘客数,运动方向,请求队列长度等来让电梯进行“预知未来”,由于本人太菜,没有完全实现这一部分,就不做讨论了。


我说自己菜,大佬说自己菜.jpg

buaaoo_second_improvement的更多相关文章

随机推荐

  1. String方法,js中Array方法,ES5新增Array方法,以及jQuery中Array方法

    相关阅读:https://blog.csdn.net/u013185654/article/details/78498393 相关阅读:https://www.cnblogs.com/huangyin ...

  2. 「FFT」题单(upd 2019.4.28)

    持续更新(last upd 2019.4.28) ZJOI2014 力 [题目链接] 解法 对原式进行转换,然后卷积FFT套上去求解就可以了. 推导过程简洁版: \[F_i=\sum_{j<i} ...

  3. 使用diff或者vimdiff比较远程文件(夹)与本地文件夹

    方法1:管道给diff $ssh eric@192.168.1.11 "cat ~/remote_file.txt" | diff - ~/local_file.txt 如果 Fi ...

  4. echart在X轴下方添加字

    使用Echart做统计图表,这个方便快捷还高大上 官方网址 https://www.echartsjs.com/ 按照文档,很快就做出了一个柱图表 在X轴下方,要显示出对应日期是星期几(上图最下方,用 ...

  5. LuoguP4233 射命丸文的笔记

    题目描述 求所有\(n\)个点带标号强连通竞赛图中哈密顿回路数量的平均值. 题解 因为要求平均数,所以我们可以把分母和分子单开来算. \(n\)个点的所有竞赛图的所有哈密顿回路个数是可以求出来的,就是 ...

  6. P1451 求细胞数量

    题目描述 一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数.(1<=m,n<=100)? 输入输出格式 输 ...

  7. P4178 Tree(点分治)

    题面要求小于等于K的路径数目,我么很自然的想到点分治(不会的就戳我) 这道题的统计答案与模板题不一样的地方是由等于K到小于等于K 那么我们可以把每一个子节点到当前根(重心)的距离排序,然后用类似双指针 ...

  8. Sublime Text 3 安装简记

    1.下载:( Sublime Text Version 3.1.1 Build 3176 ) https://www.sublimetext.com/3 2.安装Package Control: &q ...

  9. MySQL实战45讲学习笔记:索引(第五讲)

    一.需要回表的案例 在下面表T中,执行下面语句,需要执行几次树的搜索操作?会扫描多少行? select * from T where k between 3 and 5 1.初始化语句 mysql&g ...

  10. Linux ip配置

    ifconfig  查看ip ifconfig eth0  192.168.100.10  netmask 255.255.255.0  或者 ifconfig eth0  192.168.100.1 ...