1017 Queueing at Bank (25分)
思路:
写的有点乱,坑点有点多…具体在注释。
代码:
#include<iostream>//AC
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int trans(string str) {//将HH:MM:SS格式转化为数字
int h = stoi(str.substr(0, 2));
int m = stoi(str.substr(3, 2));
int s = stoi(str.substr(6, 2));
return h * 60 * 60 + m * 60 + s;
}
struct node {
int id, arrtime;//顾客序号与到达时间
};
bool cmp(node a, node b) { return a.arrtime < b.arrtime; }
int main() {
int n, k;
cin >> n >> k;
vector<int> cost(n + 1), arrtime(n + 1), win[150], wintime(k);
vector<node> info;//方便排序
for (int i = 1; i <= n; i++) {
string str;
int t, num;
node temp;
cin >> str >> t;
if (t > 60) { t = 60; }//顾客服务时间不得超过1h
num = trans(str);
arrtime[i] = num;//每个顾客到达时间
temp = { i,num };
info.push_back(temp);
cost[i] = t * 60;//每个顾客消耗时间
}
sort(info.begin(), info.end(), cmp);
for (int i = 0; i < k; i++) {
int t = info[i].id;
win[i].push_back(t);
wintime[i] = cost[t] + max(arrtime[t], 8 * 60 * 60);//max来处理全员8:00之后到的情况
}
for (int i = k; i < n; i++) {
int t = info[i].id;
auto minPosition = min_element(wintime.begin(), wintime.end());//找出最快完成服务的窗口
int w = minPosition - wintime.begin();
win[w].push_back(t);
wintime[w] += cost[t];
}
int sum = 0, cnt = 0;
for (int i = 0; i < k; i++) {//按窗口遍历
int time = max(arrtime[win[i][0]], 8 * 60 * 60);//max处理队首8:00之后到的情况
for (int j = 0; j < win[i].size(); j++) {
int t = win[i][j];
if (arrtime[t] > 17 * 60 * 60) { break; }//是否受服务由到达时间而不是接受服务时间
cnt++;
if (arrtime[t] - time > 0) {//处理队列上一个人完成后,空了一段时间才来下一个人的情况
time += arrtime[t] - time;
}
else {
sum += time - arrtime[t];
}
time += cost[t];
}
}
double ans = ((double)sum / 60) / cnt;
if (cnt == 0) { ans = 0; }//全员17:00之后到的情况
printf("%.1f", ans);
return 0;
}