问题描述
试题编号: | 201709-2 |
试题名称: | 公共钥匙盒 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 有一个学校的老师共用N个教室,按照规定,所有的钥匙都必须放在公共钥匙盒里,老师不能带钥匙回家。每次老师上课前,都从公共钥匙盒里找到自己上课的教室的钥匙去开门,上完课后,再将钥匙放回到钥匙盒中。 输入格式 输入的第一行包含两个整数N, K。 输出格式 输出一行,包含N个整数,相邻整数间用一个空格分隔,依次表示每个挂钩上挂的钥匙编号。 样例输入 5 2 样例输出 1 4 3 2 5
扫描二维码关注公众号,回复:
9731887 查看本文章
样例说明 第一位老师从时刻3开始使用4号教室的钥匙,使用3单位时间,所以在时刻6还钥匙。第二位老师从时刻2开始使用钥匙,使用7单位时间,所以在时刻9还钥匙。 样例输入 5 7 样例输出 1 2 3 5 4 评测用例规模与约定 对于30%的评测用例,1 ≤ N, K ≤ 10, 1 ≤ w ≤ N, 1 ≤ s, c ≤ 30; |
解题思路:(读题之后,观察数据范围,判断可以使用双层循环,故不需要特别关注时间复杂度)
首先构造一个Teacher类,记录某位教师使用钥匙的开始时间、结束时间以及钥匙编号;
再设一个数组key[n+1](位置 0 不用),记录位置 i 处放置的钥匙编号key[i];
由于存在同时还钥匙的情况,且还钥匙时需要按编号从小到大还,故设一个bool型数组blkey[n+1],记录当前需要归还的钥匙有哪些(false表示不需要归还,true表示需要归还);
然后设一个记录最大结束时间的变量max,控制时间的结束;
最后设置一个time变量开始判断当前时间是上课开始时间还是结束时间,正常模拟......
不过需要注意①第 i 号钥匙归还之后,blkey[i]要重置为false;②一定要先还钥匙再借钥匙。
实现代码如下:
#include<bits/stdc++.h>
using namespace std;
struct Teacher{
int start;
int end;
int roomID;
}; // k名老师使用教师
int main(){
int n, k;
scanf("%d %d",&n,&k);
Teacher tea[k];
int key[n+1] = {0}; // 第 i 个位置放置钥匙的编号
bool blkey[n+1] = {false}; // 标记该钥匙是否需要被归还,便于多枚钥匙同时归还时,从小到大还
for(int i = 1; i < n+1; i++){
key[i] = i; // 初始时,第 i 把钥匙放在位置 i 处 ( i > 0)
}
int max = 0;
for(int i = 0; i < k; i++){
int temp;
scanf("%d %d %d",&tea[i].roomID,&tea[i].start,&temp);
tea[i].end = tea[i].start + temp;
if(tea[i].end > max) max = tea[i].end; // 最晚的结束时间
}
int time = 1;
while(time <= max){ // 判断当前时间应该借钥匙/还钥匙 (若同时则先还后借)
for(int i = 0; i < k; i++){
if(time == tea[i].end){ // 可能有多位老师同时要还钥匙
blkey[tea[i].roomID] = true;
}
}
for(int i = 1; i < n+1; i++){ // 按从小到大的顺序归还钥匙
if(blkey[i]){ // 第 i号钥匙需要归还
for(int j = 1; j < n+1; j++){ // 判断是否有空位置 j
if(key[j] == 0){ // 空位置 j
key[j] = i; // 钥匙 i 放到位置 j 上
blkey[i] = false; // 放置好钥匙 i之后,重置该钥匙不需要再还
break;
}
}
}
}
for(int i = 0; i < k; i++){
if(time == tea[i].start){ // 第 i 位老师要借钥匙
for(int j = 1; j < n+1; j++){
if(key[j] == tea[i].roomID){
key[j] = 0; // 借完后该位置置为 0
break;
}
}
}
}
time++;
}
for(int i = 1; i < n+1; i++){
printf("%d ",key[i]);
}
printf("\n");
}