试题编号: | 201709-2 |
试题名称: | 公共钥匙盒 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 有一个学校的老师共用N个教室,按照规定,所有的钥匙都必须放在公共钥匙盒里,老师不能带钥匙回家。每次老师上课前,都从公共钥匙盒里找到自己上课的教室的钥匙去开门,上完课后,再将钥匙放回到钥匙盒中。 输入格式 输入的第一行包含两个整数N, K。 输出格式 输出一行,包含N个整数,相邻整数间用一个空格分隔,依次表示每个挂钩上挂的钥匙编号。 样例输入 5 2 样例输出 1 4 3 2 5 样例说明 第一位老师从时刻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; |
题目分析:
1,每把钥匙的关键元素:编号、借出时间start,归还时间end.
2,元素优先级:end相同,按照number从小到大顺序排列。
3,如果同一时刻既有老师还钥匙又有老师取钥匙,则老师们会先将钥匙全还回去再取出。
4,关于循环条件,以时刻为外层循环,待处理钥匙为内层循环。(可以记录最小开始时刻和最大结束时刻)
解法一:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int key[1500];
struct node
{
int num, sta, en;
}a[1500];
bool cmp1(node a, node b)
{
if(a.en==b.en)
return a.num < b.num;
return a.en < b.en;
}
bool cmp2(node a, node b)
{
return a.sta < b.sta;
}
int main()
{
memset(key, 0, sizeof(key));
int n, k, w, s, c;
scanf("%d%d", &n, &k);
int mi = 0x7fffffff;
int ma = -1;
for(int i=1; i<=n; i++)
key[i] = i;
for(int i=0; i<k; i++)
{
scanf("%d%d%d", &w, &s, &c);
a[i].num = w;
a[i].sta = s;
a[i].en = s+c;
mi = mi>a[i].sta?a[i].sta:mi;
ma = ma<a[i].en?a[i].en:ma;
}
sort(a, a+k, cmp2);
sort(a, a+k, cmp1);
// cout << mi << " " << ma << endl;
// for(int i=0; i<k; i++)
// cout << a[i].num << " " << a[i].sta << " " << a[i].en << endl;
while(mi <= ma)
{
for(int i=0; i<k; i++)
{
if(a[i].en==mi)
for(int j=1; j<=n;j++)
{
if(!key[j])
{key[j] = a[i].num;
break;}
}
}
for(int i=0; i<k; i++)
{
if(a[i].sta==mi)
for(int k=1; k<=n; k++)
{
if(a[i].num==key[k]&&key[k])
{key[k] = 0;
break;}
}
}
// for(int i=1; i<=n; i++)
// cout << key[i] << " ";
// cout << endl;
mi++;
}
for(int i=1; i<=n; i++)
cout << key[i] << " ";
cout << endl;
return 0;
}
/*
1 1 15
3 3 15
1 15 27
2 7 27
3 18 30
4 21 40
5 30 39
0 2 3 4 5 1
0 2 3 4 5
0 2 0 4 5
0 2 0 4 5
0 2 0 4 5
0 2 0 4 5
0 0 0 4 5
0 0 0 4 5
0 0 0 4 5
0 0 0 4 5
0 0 0 4 5
0 0 0 4 5
0 0 0 4 5
0 0 0 4 5
0 3 0 4 5
0 3 0 4 5
0 3 0 4 5
0 0 0 4 5
0 0 0 4 5
0 0 0 4 5
0 0 0 0 5
0 0 0 0 5
0 0 0 0 5
0 0 0 0 5
0 0 0 0 5
0 0 0 0 5
1 2 0 0 5
1 2 0 0 5
1 2 0 0 5
1 2 3 0 0
1 2 3 0 0
1 2 3 0 0
1 2 3 0 0
1 2 3 0 0
1 2 3 0 0
1 2 3 0 0
1 2 3 0 0
1 2 3 0 0
1 2 3 5 0
1 2 3 5 4
1 2 3 5 4
*/
解法二:使用优先队列:
注意点:
(1)结构体中的条件一定要分析清楚:
1、当借的时间相同时,若其中一个是还操作(用-1表示),则还操作优先;否则的话,按编号排序;
2、当借的时间不同时,按照借的时间排序;
(2)
把队列中的一个元素拿出来时,先要判断是不是还操作,再判断借操作;
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
int key[1050];
struct node
{
int num, sta, last;
friend bool operator <(node a, node b)
{
if(a.sta==b.sta)
{
if(a.last==-1&&b.last!=-1)//-1代表要放回,b的优先级高
return false;
else if(a.last!=-1&&b.last==-1)
return true;
else
return a.num > b.num;
}
return a.sta > b.sta;
}
};
int main()
{
int n, k, w, s, c;
scanf("%d%d", &n, &k);
memset(key, 0, sizeof(key));
priority_queue<node> que;
node temp;
for(int i=0; i<k; i++)
{
scanf("%d%d%d", &w, &s, &c);
temp.num = w;
temp.sta = s;
temp.last = c;
que.push(temp);
}
for(int i=1; i<=n; i++)
key[i] = i;
while(!que.empty())
{
node r = que.top();
que.pop();
if(r.last==-1)//如果是放操作
{
for(int i=1; i<=n; i++)
{
if(!key[i])
{
key[i] = r.num;break;
}
}
}
else //是取操作
{
node r1 = r;
r1.sta = r.sta+r.last;
r1.last = -1;
que.push(r1);
for(int i=1; i<=n; i++)
{
if(key[i]==r1.num)
{
key[i] = 0;
break;
}
}
}
}
for(int i=1; i<=n; i++)
cout << key[i] << " ";
cout << endl;
return 0;
}