题目
n个客户,k个窗口。已知每个客户的到达时间和需要的时长,如果有窗口就依次过去,如果没有窗口就在黄线外等候(黄线外只有一个队伍,先来先服务),求客户的平均等待时长。银行开放时间为8点到17点,再8点之前不开门,8点之前来的人都要等待,在17点后来的人不被服务。
Suppose a bank has K windows open for service. There is a yellow line in front of the windows which devides the waiting area into two parts. All the customers have to wait in line behind the yellow line, until it is his/her turn to be served and there is a window available. It is assumed that no window can be occupied by a single customer for more than 1 hour.
Now given the arriving time T and the processing time P of each customer, you are supposed to tell the average waiting time of all the customers.
Input Specification:
Each input file contains one test case. For each case, the first line contains 2 numbers: N (≤104) - the total number of customers, and K (≤100) - the number of windows. Then N lines follow, each contains 2 times: HH:MM:SS
- the arriving time, and P - the processing time in minutes of a customer. Here HH
is in the range [00, 23], MM
and SS
are both in [00, 59]. It is assumed that no two customers arrives at the same time.
Notice that the bank opens from 08:00 to 17:00. Anyone arrives early will have to wait in line till 08:00, and anyone comes too late (at or after 17:00:01) will not be served nor counted into the average.
Output Specification:
For each test case, print in one line the average waiting time of all the customers, in minutes and accurate up to 1 decimal place.
Sample Input:
7 3
07:55:00 16
17:00:01 2
07:59:59 15
08:01:00 60
08:00:00 30
08:00:02 2
08:03:00 10
Sample Output:
8.2
分析
跟这道题非常相似。PAT 甲级 1014
我完全照搬了1014题的思路,但是其实已经没有必要给每个窗口设置一个队列存储了。
根据我脑子里还剩余的排队论的知识, 1017 相当于单队列多服务台,它的排队等待时间应该是比较少的。???
1017相当于每个窗口只有一个人在被服务,1014相当于每个窗口排了很多人(不超过黄线)。
首先, 将顾客的到来时间按照时间顺序进行排列。(时间最好按照秒来统一单位,方便计算)没到8点就来的顾客,要记得加上他们等待开门的这段时间;超过17点的顾客就再见吧。
然后,对满足要求的顾客进行遍历。(我这里依旧沿袭了1014的思维,先排上第一轮,在去排剩余的;因为这里等待区只有1,其实可以直接进行遍历 , 参考柳神的代码)如果该窗口的上次操作完成的时间poptime大于该顾客的时间,那么该顾客需要等待;否则,就不需要等待。
最后,说一下题目有个测试点蜜汁尴尬。原文It is assumed that no window can be occupied by a single customer for more than 1 hour.这句话的意思是没有一个顾客会占用一个窗口超过一小时。但是,如果你将顾客的操作时间>60的顾客删掉,那么你将会在测试点4 扣掉2分。
代码
#include<iostream>
#include<algorithm>
#include<sstream>
#include<queue>
#include<cmath>
#include<string.h>
#include<map>
#include<stack>
using namespace std;
typedef long long ll;
int N , K;
int cnt = 0;
double waittime = 0;
struct Record
{
double time ;
double proc;
};
vector < Record > records;
struct Window
{
queue< Record > q;
double poptime;
};
Window windows[105];
bool cmp(Record a , Record b)
{
if(a.time == b.time)
return a.proc < b.proc;
else return a.time < b.time;
}
void pt(int time)
{
int hh = time / 3600;
int mm = (time - hh * 3600 ) / 60;
int ss = (time) % 60;
cout << hh << " : " << mm << " : " << ss ;
}
int main()
{
// freopen("a.txt" , "r" , stdin);
cin >> N >> K;
for(int i = 0 ; i < N; i++)
{
int hh , mm , ss , p;
char c;
cin >> hh >> c >> mm >> c >> ss >> p;
int t = hh * 3600 + mm * 60 + ss;
if(t < 8 * 3600)
{
waittime += 8 * 3600 - t;
t = 8 * 3600;
}
if(t > 17 * 3600 ) continue;
Record tmp = {t , p};
records.push_back(tmp);
// cout << tmp.time << " " << tmp.proc << endl;
cnt ++;
}
// cout << waittime << endl;
sort(records.begin() , records.end() , cmp);
int idx = 0;
if(cnt == 0)
{
cout << "0.0" ;
return 0;
}
while(idx < cnt && idx < K)//绝对不需要等待
{
windows[idx].poptime = records[idx].time + records[idx].proc * 60;
idx ++;
}
while(idx < cnt)
{
int mintime = windows[0].poptime;
int minidx = 0;
double curwait = 0;
for(int i = 1; i < K ; i ++)
{
if(windows[i].poptime < mintime)
{
mintime = windows[i].poptime;
minidx = i;
}
}
if(windows[minidx].poptime <= records[idx].time)
{
curwait = 0;
windows[minidx].poptime = records[idx].time + records[idx].proc * 60;
}
else
{
curwait = (windows[minidx].poptime - records[idx].time);
windows[minidx].poptime += records[idx].proc * 60;
}
waittime += curwait;
idx ++;
}
double ans = waittime / 60.0 / cnt;
printf("%0.1f" , ans);
}