CCF — 公共钥匙盒(Python实现:100分)

公共钥匙盒

目录

前言

一、问题描述

二、问题分析

三、程序说明


前言

最近我在做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 ≤ wN, 1 ≤ s, c ≤ 30;

对于60%的评测用例,1 ≤ N, K ≤ 50,1 ≤ wN,1 ≤ s ≤ 300,1 ≤ c ≤ 50;

对于所有评测用例,1 ≤ N, K ≤ 1000,1 ≤ wN,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=' ')

猜你喜欢

转载自blog.csdn.net/qq_36851515/article/details/83042957