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
Solution Way:
- 以秒为单位处理数据。
- 定义消费者结构体,包含到达时间和处理业务所需时间。
- 8点之前到达的消费者需要等待,17点之后到达的消费者则银行不为其服务。
- 思路:
- 以消费者到达时间排序
- 让一部分消费者去每一个窗口办理业务(即每个窗口有一个消费者)
- 找出最先办完业务的消费者(称之为‘旧消费者’),并记录该消费者所在的窗口
- 计算旧消费者办理完业务的时间,分两种情况:
- 旧消费者到达时,该窗口空闲,则他直接去办理业务
- 旧消费者到达时,该窗口已在办理业务,则他需要等待
- 更改办理业务的消费者(移旧换新),计算新的消费者等待时间
Solution Code:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef struct customer
{
int arrive;
int process;
}customer;
int windows_time[101]; // 计时器
int windows_queue[101] = {0}; // 当前正在处理业务的消费者
customer cus[10002] = {0};
double total_wait = 0;
bool compare(customer a, customer b)
{
return a.arrive < b.arrive;
}
int main()
{
int n, k;
cin >> n >> k;
for (int i = 0; i < n; ++i) {
int hour, minute, second, process;
scanf("%d:%d:%d %d", &hour, &minute, &second, &process);
cus[i].arrive = 3600*hour + 60*minute + second;
cus[i].process = 60*process;
}
// sort by arrive small --> big
sort(cus, cus+n, compare);
//08:00:00 = 28800sec 17:00:00 = 61200sec
for (int i=0; i<101; ++i)
windows_time[i] = 28800;
int total_customers = n;
// 先为每一个窗口安排一个消费者
for (int i = 0; i < k; ++i) {
if (i >= n) break; //消费者的数目小于窗口数目
if (cus[i].arrive > 61200) {
total_customers = i;
break;
}
if (cus[i].arrive < 28800) //八点之前到达
total_wait += (28800 - cus[i].arrive);
windows_queue[i] = i;
}
for (int i = k; i < n; ++i) {
if (cus[i].arrive > 61200) {
total_customers = i;
break;
}
int early_time = 999999999;
int windows_id;
// 找到最先办完业务的窗口
for (int j = 0; j < k; ++j) {
if (windows_time[j]+cus[windows_queue[j]].process < early_time) {
early_time = windows_time[j] + cus[windows_queue[j]].process;
windows_id = j;
}
}
int last_customer = windows_queue[windows_id]; // 办理完业务的顾客
// 办完业务的消费者离开,新的消费者办理业务
windows_queue[windows_id] = i;
// 更新办完业务的消费者离开时的窗口时间
if (windows_time[windows_id] >= cus[last_customer].arrive)
windows_time[windows_id] += cus[last_customer].process;
else
windows_time[windows_id] = cus[last_customer].arrive + cus[last_customer].process;
// 计算新的消费者等待的时间
if (windows_time[windows_id] >= cus[i].arrive)// 来早了,需要等待
total_wait += (windows_time[windows_id] - cus[i].arrive);
}
printf("%.1lf\n", total_wait/(60*total_customers));
return 0;
}