这道题好像很多人的方法是设置一个大时钟,一分钟一分钟地循环。我的方法是一旦有人处理完了事务,时间就跳到那个时刻,这样可以少走很多次循环。
题目描述
假设银行有K个窗口提供服务,窗口前设一条黄线,所有顾客按到达时间在黄线后排成一条长龙。当有窗口空闲时,下一位顾客即去该窗口处理事务。当有多个窗口可选择时,假设顾客总是选择编号最小的窗口。
本题要求输出前来等待服务的N位顾客的平均等待时间、最长等待时间、最后完成时间。
输入
输入第1行给出正整数N(≤1000),为顾客总人数;随后N行,每行给出一位顾客的到达时间
T
和事务处理时间P
,并且假设输入数据已经按到达时间先后排好了顺序;最后一行给出正整数K(≤10),为开设的营业窗口数。输出
在一行中输出平均等待时间(输出到小数点后1位)、最长等待时间、最后完成时间,之间用1个空格分隔,行末不能有多余空格。
输入样例1
9
0 20
1 15
1 61
2 10
10 5
10 3
30 18
31 25
31 2
3
输出样例1
6.2 17 62
#include <iostream>
#include <queue>
using namespace std;
typedef struct {
int T, P;
}Time;
int main() {
int now = 0, Wait = 0 , totalWait = 0, maxWait = 0, flag = 0, fin = 999;
double N;
int k;
cin >> N;
queue<Time>Q;
Time t;
double n = N;
while (N--) {
cin >> t.T >> t.P;
Q.push(t);
}
cin >> k;
int emp = k;
int** K = new int*[k];
for (int i = 0; i < k; i++)
K[i] = new int[2];
for (int i = 0; i < k; i++)
for (int j = 0; j < 2; j++)
K[i][j] = 0;
while (!flag) {
if (!emp&&!Q.empty()) {
int itemp = 0;
fin = 999;
for (int i=0; i < k; i++) {
if (K[i][0] + K[i][1] < fin) {
fin = K[i][0] + K[i][1];
itemp = i;
}
//窗口满时找到能最快处理完的任务
//等待时间=最快那个的完成时刻-等待任务的到达时刻
}
Wait = fin - Q.front().T;
if(Wait>0) {
totalWait += Wait;
if (Wait > maxWait)
maxWait = Wait;
now = fin;
}
else {
now = Q.front().T;
}
K[itemp][0] = 0;
K[itemp][1] = 0;
emp++;
}
if (emp&&!Q.empty()) {
for (int i = 0; i < k; i++) {
if (K[i][0] == 0 && K[i][1] == 0 && !Q.empty()) {
if (now)
K[i][0] = now;
else {
now = Q.front().T;
K[i][0] = now;
}
K[i][1] = Q.front().P;
Q.pop();
emp--;
break;
}
}
}
if (Q.empty()) {
for (int i = 0; i < k; i++) {
if (K[i][1] != 0 && K[i][0] != 0) {
if (K[i][1] + K[i][0] > fin) {
fin = K[i][1] + K[i][0];
now = fin;
}
}
}
flag = 1;
}
}
double avg;
avg = totalWait / n;
printf("%.1f", avg);
cout <<' ' << maxWait << ' ' << now << endl;
}