试题请参见: http://pat.zju.edu.cn/contests/pat-a-practise/1016
题目概述
假设有N个客户在K个窗口等待服务。 每个窗口可以容纳一个人, 因此其他客户需要进行等待. 当某个客户服务完成后, 下一个客户可以进入该窗口并被服务. 我们假设没有窗口会被占用1小时以上.
现在我们给出每个客户的到达时间T和服务该客户所需要的时间P, 请计算所有客户的平均等待时间.
输入
每个输入文件包含一个测试用例. 每个测试用例, 第一行包含两个整数N( <= 1000)和K( <= 100). 其中N表示客户的数量, K表示窗口的数量. 接下来的N行, 包含两个时间: HH:MM:SS, 表示客户的到达时间; P, 表示服务该客户所需要的时间(以分钟为单位). HH的范围是[00, 23], MM和SS的范围是[00, 59]. 我们假设没有两个客户在同一时间到达.
需要说明的是, 银行的营业时间是08:00-17:00. 如果到达的时间早于08:00, 客户需要等待至银行开始营业才能被服务; 如果客户晚于(或恰好在)17:00:01到达银行, 则该客户不会被服务, 因此也无需计算该客户的平均等待时间.
输出
对于每一个测试用例, 请输出客户的平均等待时间, 以分钟为单位, 并精确到一位小数.
解题思路
典型的模拟题, 并且比PAT 1014要简单一点的模拟题.
读入数据时, 自动过滤17:00:00以后到达的客户.
按客户先后到达顺序进行服务, 在客户服务完成后, 更新窗口的服务完成时间.
客户每次选择服务完成时间最短的进行排队(服务).
需要考虑如下情况:
- 若银行未营业, 则客户需要等待;
(以及在“遇到的问题”中阐述的一些情况)
遇到的问题
若干次WA, 存在如下需要考虑的情况
1. 若所有顾客都在17:00:00以后到达, 则结果为0.0; 2. 若当前所有顾客都已服务完毕, 但是下一位顾客还未到来, 需要窗口需要等待; 3. 若当前客户不需要等待, 则该窗口服务完成时间时为客户到达时间 + 服务时间; 否则, 该窗口服务完成时间为上一个客户完成的时间 + 该客户服务时间.
源代码
#include <iostream>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <string>
#include <vector>
const std::string BANK_OPEN_TIME = "08:00:00";
const std::string BANK_CLOSE_TIME = "17:00:00";
struct Customer {
std::string arrivedTime;
int waitingTime; // seconds
int processingTime; // seconds
Customer() {
waitingTime = 0;
processingTime = 0;
}
};
struct Window {
int currentTime; // seconds
Window() {
currentTime = 0;
}
};
int atoi(char timeDigit0, char timeDigit1) {
return (timeDigit0 - '0') * 10 + (timeDigit1 - '0');
}
int getIntervalBetweenTime(const std::string& startTime, const std::string& endTime) {
if ( startTime >= endTime ) {
return 0;
}
int startHour = atoi(startTime[0], startTime[1]);
int startMinute = atoi(startTime[3], startTime[4]);
int startSecond = atoi(startTime[6], startTime[7]);
int endHour = atoi(endTime[0], endTime[1]);
int endMinute = atoi(endTime[3], endTime[4]);
int endSecond = atoi(endTime[6], endTime[7]);
int interval = (endHour - startHour) * 3600 + (endMinute - startMinute) * 60
+ (endSecond - startSecond);
return interval;
}
int getIntervalBetweenTime(const std::string& startTime, int endTime) {
int startHour = atoi(startTime[0], startTime[1]);
int startMinute = atoi(startTime[3], startTime[4]);
int startSecond = atoi(startTime[6], startTime[7]);
int interval = endTime - ((startHour - 8) * 3600 + startMinute * 60 + startSecond);
return (interval > 0 ? interval : 0);
}
int getCustomerCompleteTime(std::string& arrivedTime, int processingTime) {
if ( arrivedTime < BANK_OPEN_TIME ) {
arrivedTime = BANK_OPEN_TIME;
}
int arrivedHour = atoi(arrivedTime[0], arrivedTime[1]);
int arrivedMinute = atoi(arrivedTime[3], arrivedTime[4]);
int arrivedSecond = atoi(arrivedTime[6], arrivedTime[7]);
int completeTime = (arrivedHour - 8) * 3600 + arrivedMinute * 60 + arrivedSecond + processingTime;
return completeTime;
}
bool customerCompare(const Customer& customer1, const Customer& customer2) {
return customer1.arrivedTime < customer2.arrivedTime;
}
int main() {
// std::ifstream cin;
// cin.open("input.txt");
using std::cin;
int n = 0, k = 0;
cin >> n >> k;
std::vector<Customer> customers;
std::vector<Window> windows(k);
// Input
for ( int i = 0; i < n; ++ i ) {
Customer customer;
cin >> customer.arrivedTime >> customer.processingTime;
if ( customer.arrivedTime <= BANK_CLOSE_TIME ) {
customer.processingTime *= 60;
customers.push_back(customer);
}
}
// Processing
std::sort(customers.begin(), customers.end(), customerCompare);
size_t customerIndex = 0;
for ( ; customerIndex < k && customerIndex < customers.size(); ++ customerIndex ) {
Customer& customer = customers[customerIndex];
Window& window = windows[customerIndex];
customer.waitingTime = getIntervalBetweenTime(customer.arrivedTime, BANK_OPEN_TIME);
window.currentTime += getCustomerCompleteTime(customer.arrivedTime, customer.processingTime);
}
for ( ; customerIndex < customers.size(); ++ customerIndex ) {
int firstCompleteWindowIndex = 0, firstCompleteWindowTime = 1 << 30;
// Search for a window to serve
for ( size_t i = 0; i < windows.size(); ++ i ) {
if ( windows[i].currentTime < firstCompleteWindowTime ) {
firstCompleteWindowTime = windows[i].currentTime;
firstCompleteWindowIndex = i;
}
}
Customer& customer = customers[customerIndex];
Window& window = windows[firstCompleteWindowIndex];
customer.waitingTime = getIntervalBetweenTime(customer.arrivedTime, window.currentTime);
int completeTime = getCustomerCompleteTime(customer.arrivedTime, customer.processingTime);
if ( customer.waitingTime == 0 ) {
window.currentTime = completeTime;
} else {
window.currentTime += completeTime;
}
}
// Output
double averageWaitTime = 0;
for ( size_t i = 0; i < customers.size(); ++ i ) {
averageWaitTime += customers[i].waitingTime;
}
if ( customers.size() != 0 ) {
averageWaitTime /= customers.size() * 60;
}
std::cout << std::fixed << std::setprecision(1) << averageWaitTime << std::endl;
return 0;
}