hiho一下第202周《Registration Day》题目分析

1
0

《Registration Day》题目分析

本题是一道非常复杂的模拟题。不仅需要模拟整个注册过程,还需要利用优先队列等数据结构减少时间复杂度。

冷静分析之后可以发现整个注册过程中有三种事件:

1)某位同学到达某个Office

2)某位同学进入某个Office开始办理手续

3)某位同学办完手续离开某个Office

一种事件发生后可能会出发另一种事件。例如:

某位同学到达某个Office(1类事件),如果当前Office空闲,那么会触发这位同学在这个Office开始办理手续的事件(2类事件)。

而2类也会触发相应的3类事件。

3类事件会触发:(1)该同学到达下一个Office (2)另一位同学进入该Office开始办理手续。

我们可以把所有事件都放在优先队列里(按时间排序,时间相同按学生学号排序),模拟的过程就是处理队首事件,同时将新产生的事件加入队列的过程。

基本思路是:

while(事件队列不为空):
    e = 队首事件
    if e 是1类事件:
        if e.office当前空闲且等待队列为空:
            新事件 e2 = e.student在e.office开始办理手续,时间e.time
            e2加入事件队列
        else:
            将e.student加入e.office的等待队列
    if e 是2类时间:
        e.office标记为不空闲
        新事件 e2 = e.student离开e.office,时间e.time + 办理时间
        e2加入事件队列
    if e 是3类事件:
        e.office标记为空闲
        if e.student 后面还有手续要办:
            新事件 e3 = e.student到达e.student.next_office(e.office),时间e.time + K  
            e3加入事件队列
        else:
            记录e.student的完成时间
        if e.office的等待队列不为空
            student = 等在e.office的队首同学(到达最早,学号最小)
            新事件 e4 = student进入e.office开始办理手续,时间e.time
            e4加入事件队列

在基本思路的基础上可以有一些优化,让程序更简单。比如我们可以只记录1类事件,省略23类事件,即模拟时一个1类事件直接产生下一个1类事件(该同学到达下一个Office)。

这要求我们再额外记录一个数据,就是每个office最早的空闲时间:

while(事件队列不为空):
    e = 队首事件
    start_time = max(e.time, e.office最早空闲时间)
    finish_time = e.time + 办理时间
    e.office最早空闲时间 = finish_time  
    if e.student 后面还有手续要办:
        新事件 e2 = e.student到达e.student.next_office(e.office),时间finish_time + K    
        e2加入事件队列  
    else:
        记录e.student的完成时间finish_time

0 answer(s)

write answer 切换为英文 切换为中文


转发分享