寒假作业2
地址:……
* 题目背景
一栋10层的大楼(楼层编号1-10),设有一台无限载重的电梯,初始时电梯停在1层。电梯移动1层的耗时为1,在某一层停靠的耗时为1(时间初始为0)。为了使得乘客等待的时间(电梯在目的层的停靠时刻 - 乘客发出请求时刻)总和最小,请你编写一个程序来进行电梯调度。
输入有5个请求,每个请求一行,格式为请求时刻 起始楼层数 去往方向,其中方向为0代表向上去往10层,为1代表向下去往1层。
输出每次对应的决策,每一行的输出格式为xx时,停靠在x楼。其中,“xx时刻”指的是在某层楼停靠的时刻,且不算入在该层的停靠时间。如:
- 当0时刻时,电梯此时在1层,输入有0 1 0,那么电梯从1层接客(1s)前往10层(9s),应输出10时,停靠在10楼(1+9=10)。此时,该乘客等待时间为(10-0=)10。
- 当0时刻,电梯此时在1层,输入有0 2 0,那么电梯从1层前往2层(1s),接上乘客(1s),前往10层(8s),应输出10时,停靠在10楼(1+1+8=10)。此时,该乘客等待时间为(10-0=)10s。
最后输出完成5个请求(所有乘客都到达目的地)后,各乘客的等待时间总和。
ANS 1
分析
EMMM先看这个题目虽然觉得能随时变换方向还不消耗时间的电梯有点魔幻hhh(关注点不要在这里啦!)
好了看到没有时间的限制和其他的要求,我脑海里第一个跳出的就是暴搜(毕竟暴力出奇迹OTL)那么再来看数据点,经过简单分析,很明显,排除了某些213乘客会走楼梯的情况,那么大多数乘客只会在原地等待,因此,停靠在别的楼层是很显然没有意义的,如此一来,电梯只会在我们请求的地点(5个)+1楼+10楼停靠,当然,5个地点中也有可能会重复……
好啦接下来看数据构造
数据模型
关于乘客
struct{
int time;//记录这名乘客发出请求的时刻
int ceng;//记录这名乘客发出请求的层数
int flag;//记录这名乘客去的方向 0表示向下,1表示向上
int zhuang;//记录这名乘客的状态 0表示等待进入,1表示在电梯中,2表示已经下电梯
int value;//记录这名乘客的到达时间:到达的时间-发出请求的time
}r[1004];
这个结构体是乘客的信息记录,其中value是我第一次算时间的时候太213了(其实是太弱)构造出来的,结果写起来非常麻烦也没有必要,想了好久,后来发现其实只要算电梯当前时间-乘客请求时间=等待时间就可以了,也就是在1楼和10楼进行统计
关于电梯
struct {
int time;//记录当前的时间
int floor;//电梯当前所在的楼层
int flag;//记录现在取得方向,有0 10两种
}dt;
这个东西实在DFS中记录实时情况的,对他进行更新,也就是所等待的时间即
abs(dt.time-r[i].time)在+1S+1S+1S(简直续命游戏)
这样后面的+1S可以在每次停靠的时候模拟处理+1S
数据更新
关于更新写了3个处理,也就是在1楼、10楼、和其他请求楼层
10楼
if(n==10)
for(int i=1;i<=5;i++)
if(r[i].flag==1&&r[i].zhuang==1)
{
r[i].zhuang=2;
}
//如果当前是第10层,让电梯中需要出去的人出去
而1楼、和其他楼层依次类推,只需要让需要下车的人下车,需要上的人更新就行,需要注意的一点是我之前没有考虑到的,在之后回溯的时候,需要还原,而就需要开个数组记录这些下车或上车的人,把他们再还原丢出去。
最终目标
我们搜到的最终目标也就是让所有人的状态都变成2,也就是到达目的地为止,这样所有的请求都已经应答
实现
如此一来我们就可以根据上面的几个构造直接暴搜DFS遍历最优解,也就是第K次决策,停靠在……最后取最少时间
辛酸的心路历程(BUG处理)
之前第一次没认真看的时候觉得还行,就是模拟,后来发现细节有一点多……(哭的像个两百斤的狗子、、特别是+1S的续命游戏一开始没有加上去)
上面有提到的那个统计时间一开始纠结了好久,没有想到怎么去更新把时间弄上去,所以才会开了一个VALUE来记录,后来发现不用,因为电梯的信息也是要记录的,就减一下就OK
0 和 1也就是1和10写反了……找了好久
细节的初始化和回溯……开了比较多的东西记录,一些边界还有初始化的修改出了比较大的问题,反复都在改这个