PAT甲级 1017 Queueing at Bank
原题链接
https://pintia.cn/problem-sets/994805342720868352/exam/problems/type/7?problemSetProblemId=994805491530579968&page=0
题目大意
题目大意:有n个客户,k个窗口。已知每个客户的到达时间和需要的时长,如果有窗口就依次过去,如果没有窗口就在黄线外等候(黄线外只有一个队伍,先来先服务),求客户的平均等待时长。银行开放时间为8点到17点,再8点之前不开门,8点之前来的人都要等待,在17点后来的人不被服务。
解题思路
用结构体表达客户的到达时间和办理业务时间,首先把所有hh:mm:ss格式的时间全化成以当天0点为基准的秒数,这样方便处理。注意晚于17:00的客户不算在内
对客户按照到达时间从小到大进行排序。使用一个优先队列维护窗口办理完业务的时间。详细见代码和注释。
代码(CPP)
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
#define endl "\n"
const int maxn = 1e4 + 10;
const ll INF = 0x3f3f3f3f3f3f3fLL;
struct person {
int arrived;
int time;
} p[maxn];
bool cmp(person &a, person &b) {
return a.arrived < b.arrived;
}
void solve() {
int n, k;
cin >> n >> k;
int cnt = 0;
for (int i = 1; i <= n; i++) {
int h, m, s, t;
char c;
cin >> h >> c >> m >> c >> s >> t;
int second = h * 3600 + m * 60 + s;
if (second >= 61200)
continue;
p[++cnt].arrived = second;
p[cnt].time = t * 60;
}
sort(p + 1, p + cnt + 1, cmp);
priority_queue<int, vector<int>, greater<int>> q;
for (int i = 1; i <= k; i++)
q.push(28800);
double sumWait = 0;
for (int i = 1; i <= cnt; i++) {
if (q.top() <= p[i].arrived) { // 当前最早完成业务的窗口时间早于当前客户到达时间,则该客户不需要等待
q.pop();
q.push(p[i].arrived + p[i].time); // 维护当前客户业务完成时间
} else { // 当前最早完成业务的窗口时间晚于当前客户到达时间,则该客户需要等待
sumWait += q.top() - p[i].arrived; // 记录等待时间
q.push(q.top() + p[i].time); // 维护当前客户业务完成时间,注意需要等当前窗口完成上一个业务
q.pop();
}
}
if (cnt != 0)
cout << setprecision(1) << sumWait / cnt / 60 << endl;
else
cout << "0.0" << endl;
}
int main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout << fixed;
cout.precision(18);
solve();
return 0;
}