公共钥匙盒
目录
前言
最近我在做CCF的题目,也打算把每道题的解题思路都写到博客上来,希望能帮助到也在做CCF题目的读者们,希望你们通过本文能有所提示,帮助大家提升编程能力。另外有个很好的想法就是,建议读者们可以先看一下问题分析的部分,然后自己再整理一下思路,重新做一遍,最后再参考代码,我想这样会更有收获。
一、问题描述
问题描述
有一个学校的老师共用N个教室,按照规定,所有的钥匙都必须放在公共钥匙盒里,老师不能带钥匙回家。每次老师上课前,都从公共钥匙盒里找到自己上课的教室的钥匙去开门,上完课后,再将钥匙放回到钥匙盒中。
钥匙盒一共有N个挂钩,从左到右排成一排,用来挂N个教室的钥匙。一串钥匙没有固定的悬挂位置,但钥匙上有标识,所以老师们不会弄混钥匙。
每次取钥匙的时候,老师们都会找到自己所需要的钥匙将其取走,而不会移动其他钥匙。每次还钥匙的时候,还钥匙的老师会找到最左边的空的挂钩,将钥匙挂在这个挂钩上。如果有多位老师还钥匙,则他们按钥匙编号从小到大的顺序还。如果同一时刻既有老师还钥匙又有老师取钥匙,则老师们会先将钥匙全还回去再取出。
今天开始的时候钥匙是按编号从小到大的顺序放在钥匙盒里的。有K位老师要上课,给出每位老师所需要的钥匙、开始上课的时间和上课的时长,假设下课时间就是还钥匙时间,请问最终钥匙盒里面钥匙的顺序是怎样的?
输入格式
输入的第一行包含两个整数N, K。
接下来K行,每行三个整数w, s, c,分别表示一位老师要使用的钥匙编号、开始上课的时间和上课的时长。可能有多位老师使用同一把钥匙,但是老师使用钥匙的时间不会重叠。
保证输入数据满足输入格式,你不用检查数据合法性。
输出格式
输出一行,包含N个整数,相邻整数间用一个空格分隔,依次表示每个挂钩上挂的钥匙编号。
样例输入
5 2
4 3 3
2 2 7
样例输出
1 4 3 2 5
样例说明
第一位老师从时刻3开始使用4号教室的钥匙,使用3单位时间,所以在时刻6还钥匙。第二位老师从时刻2开始使用钥匙,使用7单位时间,所以在时刻9还钥匙。
每个关键时刻后的钥匙状态如下(X表示空):
时刻2后为1X345;
时刻3后为1X3X5;
时刻6后为143X5;
时刻9后为14325。
样例输入
5 7
1 1 14
3 3 12
1 15 12
2 7 20
3 18 12
4 21 19
5 30 9
样例输出
1 2 3 5 4
评测用例规模与约定
对于30%的评测用例,1 ≤ N, K ≤ 10, 1 ≤ w ≤ N, 1 ≤ s, c ≤ 30;
对于60%的评测用例,1 ≤ N, K ≤ 50,1 ≤ w ≤ N,1 ≤ s ≤ 300,1 ≤ c ≤ 50;
对于所有评测用例,1 ≤ N, K ≤ 1000,1 ≤ w ≤ N,1 ≤ s ≤ 10000,1 ≤ c ≤ 100。
二、问题分析
不管做什么题,最重要的还是思路,先把逻辑整理好,基本的程序框架就有了,突然听到老师的一句话,顺便分享给大家:“自顶向下,逐步细化”。
本题主要的解题思路如下:
①先大致梳理一下解题步骤:输入数据的部分就不详说了,遍历每一秒,遵循先还后借的原则,找出每一秒要还的钥匙,然后按编号从小到大的还回去;再找出要借的钥匙,然后把它们借出去
②知道大致逻辑就可以逐步细化了,先遍历每一秒,如何遍历?把开始上课时间+上课时长就等于要还钥匙的时间点,然后找出其最大值,即整个过程持续的时间就是该最大值
③先制定规则:比如钥匙编号为1,2,3,4,5;要借钥匙3,则把编号3置为0,表示借出去了,还回来先判断该位置是否是0,是0才能还回钥匙
④每过一秒,就判断是否有要还的钥匙,如果有,按编号从小到大、从左到右依次还回钥匙;接着判断是否有要解答钥匙,如果有,遍历钥匙列表找出指定钥匙,将其置为0,表示借出去了。
⑤基本的解题框架就是如此,说的好像有点复杂,希望你们能理解,(还在想有没有更简便的方法,如果有欢迎讨论)。
三、程序说明
n:输入n把钥匙
k:表示要输入k行钥匙的使用情况
key:存储n把钥匙的编号
info:输入钥匙的使用情况:钥匙编号、开始上课的时间和上课的时长
start_time:存储借钥匙的时间点
end_time:存储还钥匙的时间点
return_key:存储要还的钥匙列表
lend_key:存储要借的钥匙列表
return_lend_key(info,time):该函数作用是找出要借的,或者要还的钥匙,并存储在一个RL_key列表中
python语言的程序如下(100分):
# 公共钥匙盒
# 找出要借,或者要还的钥匙编号
def return_lend_key(info,time):
RL_key = []
for i in range(0, len(time)):
if time[i] == t:
RL_key.append(info[i][0])
return RL_key
n,k = input().split()
n = int(n)
k = int(k)
key = [i for i in range(1,n+1)] # 钥匙盒
info = [[0 for i in range(3)] for j in range(k)] # 存放钥匙使用情况
for i in range(k):
info[i][:] = [int(wsc) for wsc in input().split()]
for i in range(k):
info[i][2] = info[i][1] + info[i][2]
start_time = [i[1] for i in info] # 二维列表切片操作
end_time = [i[2] for i in info]
for t in range(1,max(end_time)+1):
# 先还后借
# 还
if t in end_time:
return_key = return_lend_key(info,end_time) # 找出要还的钥匙
return_key.sort()
for r in range(len(return_key)):
for i in range(n):
if key[i] == 0:
key[i] = return_key[r]
break
# 借
if t in start_time:
lend_key = return_lend_key(info, start_time) # 找出要借的钥匙
for r in range(len(lend_key)):
for i in range(n):
if key[i] == lend_key[r]:
key[i] = 0
for i in key:
print(i,end=' ')