1014 Waiting in Line (30 分)
今天给大家分享一道PAT甲级的小题,考察点:排队论
简单翻译:
银行有N个窗口,每个窗口前可以站M个人,一共有K个人,他们最初按照1 - K的编号排队,起初所有人在黄线后面等待,如果某个窗口有空缺,等待的人就会顶上去,如果同一时间有很多空缺的,按照窗口编号的顺序顶上去。窗口为第 i 个人服务time[i]分钟。
问:这里有一串请求,表示第 j 个人在询问自己完成服务的时间是多少。如果完成完成时间在17:00以内,就输出这个时间,如果超过了17:00,就给客户输出Sorry。
思路:
简单的排队论,因为时间的范围并不是很大,从8:00-17:00只有540分钟,所以这里可以对每一分钟进行遍历。遍历的同时维护N个队列的状态。最终输出结果。
具体来说:
我们申请N个队列,每个队列的容量是M,起初先把K个人往队列里面填,可能可以填满,可能填不满。接着以分钟为基本单位处理每个分钟下的状态即可。
小坑 :
按照常理来说,银行是17:00下班,但是如果银行在16:59开始处理你的事务,需要处理10分钟,他不会说还有1分钟就下班了,你明天再来吧这种话吧。所以如果再下班前已经开始处理某个人的信息的时候,这个人的信息是要处理完的。所以是有可能输出比17:00更大的数据的。注意到这一点,这个题就没有什么坑了。
C++ 代码:
#include"bits/stdc++.h"
#define all(x) x.begin(),x.end()
#define len(x) x.size()
#define INF (1e9)
#define vi vector<int>
#define ll long long int
#define ull unsigned long long int
#define db double
#define vvi vector<vector<int>>
#define pb(x) push_back(x);
using namespace std;
void f(int i) {
int H = i / 60;
int min = i % 60;
printf("%02d:%02d\n", 8 + H, min);
}
int main() {
int N, M, K, Q;
cin >> N >> M >> K >> Q;
vi time(K);
for (int i = 0; i < K; i++) {
cin >> time[i];
}
//pair.first 表示这是第几个人,pair.second表示这个人还需要成立多长时间
vector<queue<pair<int, int>>> q(N, queue<pair<int, int>>());
//t表示还没有入队的第一个人
int t = 0;
for (int i = 0; i < min(N * M, K); i++) {
q[(t) % N].push(make_pair(t + 1, time[t]));
t++;
}
vi quire(Q);
for (int i = 0; i < Q; i++) {
cin >> quire[i];
}
vi s(K, 0);
//从8:00-17:00只有540分钟
for (int i = 1; i <= 540; i++) {
for (int j = 0; j < N; j++) {
if (len(q[j]) != 0) {
q[j].front().second--;
if (q[j].front().second == 0) {
s[q[j].front().first] = i;
q[j].pop();
if (t < K) {
q[j].push(make_pair(t + 1, time[t]));
t++;
}
}
}
}
}
//处理那些已经下班了,还没处理完的用户,要加班给人家处理一下
for (int i = 0; i < N; i++) {
if (len(q[i]) != 0) {
if (time[q[i].front().first - 1] != q[i].front().second) {
s[q[i].front().first] = 540 + q[i].front().second;
}
}
}
for (int i = 0; i < Q; i++) {
if (s[quire[i]] != 0) {
f(s[quire[i]]);
} else {
cout << "Sorry" << endl;
}
}
return 0;
}