if __name__ == '__main__':
N,K=[int(i) for i in input().split()]
cus = {} #用来存放顾客的到达时间,和需要处理的时间
window = [3600 * 8] * K #将所有窗口的开放时间都设为8点
for _ in range(N):
A=input().split()
hh,mm,ss=[int(i) for i in A[0].split(":")]
wait=int(A[1])
if hh*3600+mm*60+ss<17*3600+1: #过滤掉晚上5点以后的顾客
cus[hh*3600+mm*60+ss]=wait*60
cus=dict(sorted(cus.items(),key=lambda x:x[0])) #按照到达时间把顾客排好队
total=0
for j in cus:
window=sorted(window) #不断的更新窗口的等待时间,将短的等待时间放在前面
if window[0]>j: #判断窗口是否空闲
total+=window[0]-j #将顾客等待时间存放入
window[0]+=cus[j] #更新窗口下次开放的时间
else:
window[0]=cus[j]+j
count=len(cus)
if count>0:
print("{:.1f}".format(total/60/count))
else:
print("0.0")
本题参考了一位,用C++博主写的答案:
https://blog.csdn.net/LostStephon/article/details/48878633
(1)给出N个人的到达银行的时间和需要被服务的时间,在K个窗口的情况下,求出所有人的平均等待时间,对于5点以后到达的人不计算在内。
(2)看似是排队的问题,需要先固定每个人在哪个窗口队列的哪个位置以及他前面的人的服务时间,同时也依赖于他的到达时间和当前第一个人被服务了多长时间,这样看来问题变得复杂了许多,我们将问题简化成这样:每个窗口只维护自己的空闲时刻(8:00开始),谁最先空闲了,就选择等待队列中最早到达银行的开始服务,这样这个人的等待时间就等于此窗口的空闲时刻-客户到达时刻,注意:若此值为正,说明这个窗口在服务上一个人期间,这个人就到达了,他需要等待,若小于等于0,说明此人在这个窗口空闲时刻之前都还没有到达银行,那么可想而知,一旦他到达银行,他不需要等待,直接获取服务,服务结束后,更新此窗口的空闲时刻。依次类推,直到队列为空或者只剩下17:00以后到达的人。
(3)为了计算的方便,我们将所有的时刻全部算成秒,如:8:00就是8*3600秒
(4)每次都要计算最先空闲的窗口,因此必然涉及到排序。
(5)在服务结束后,更新窗口的空闲时刻需要注意:若客户到达的时候,窗口不空闲,那么意味着这个窗口服务完上一个人后立即服务这个人,因此这个窗口的下一次空闲时刻是本次空闲时刻+此人的服务时间,反之,若在空闲时刻时候到达的,那么窗口一直要等到他到达银行,再给他服务,因此下一次的空闲时刻=此人到达时间+服务时间