题目大意
有n个客户,k个窗口。已知每个客户的到达时间和需要的时长,如果有窗口就依次过去,如果没有窗口就在黄线外等候(黄线外只有一个队伍,先来先服务),求客户的平均等待时长。银行开放时间为8点到17点,再8点之前不开门,8点之前来的人都要等待,在17点后来的人不被服务。题目还有一个坑点It is assumed that no window can be occupied by a single customer for more than 1 hour.这句话没被用上,如果超过一小时的客户拒绝服务,则第四个测试点会过不去,那意思应该是到了60分钟就让这个人重新排队,那问题来了是重新排在第一个位置还是排在最后一个位置呢?根据测试点给出的数据是排在第一个位置。这就很郁闷了,让他重排还有什么意义吗?所以对于这种超过60分钟的人应该怎么处理?题目直接没处理!既然如此直接不限时不就好了吗,加这一句不是存心误导考生吗?我认为这是这道题的不严谨和疏漏之处。思路解析
客户结构体node,里面有come为到达时间和process为需要服务的时长。先将所有满足条件的(到来时间点在17点之前的)客户放入数组中,数组的长度就是需要服务的客户的个数。windows数组表示某个窗口的结束时间,一开始所有窗口的值都为8点整。每一个客户到来的时候,选择最早结束时间的窗口,如果最早结束时间比他还早,那么他一来就能被服务,更新window的值;如果最早结束时间比他晚,他需要等待,累加等待的时间,然后更新window的值。 对所有客户要先进行排序,按来的时间的早晚排序,之后再先来先服务。因为涉及分钟和秒数,可以把所有时间暂时先化解成秒数的形式,便于计算。示例代码
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
class Node {
public:
int come;//秒
double process;//秒
};
bool cmp(Node n1, Node n2) {
return n1.come < n2.come;
}
int main() {
int n, k;
scanf("%d %d", &n, &k);
double sum = 0.0;
vector<Node> custom;//存放所有符合条件的顾客
vector<double> windows(k, 28800);//元素为当前时间
for (int i = 0; i < n; i++) {
int a, b, c;
double d;
scanf("%d:%d:%d %lf", &a, &b, &c, &d);
int cometime = a * 3600 + b * 60 + c;
if (cometime > 17 * 3600) continue;
Node n;
n.come = a * 3600 + b * 60 + c;
n.process = d * 60;
custom.push_back(n);
}
sort(custom.begin(), custom.end(), cmp);
for (int i = 0; i < custom.size(); i++) {
sort(windows.begin(), windows.end());
if ((windows[0] - custom[i].come) > 0) {//来早了就得等
sum += (windows[0] - custom[i].come);
windows[0] += custom[i].process;
}
else {
windows[0] = custom[i].come + custom[i].process;
}
}
printf("%.1f\n", sum / custom.size() / 60);
return 0;
}