7-48 银行排队问题之单窗口“夹塞”版 (30 分)

7-48 银行排队问题之单窗口“夹塞”版 (30 分)

排队“夹塞”是引起大家强烈不满的行为,但是这种现象时常存在。在银行的单窗口排队问题中,假设银行只有1个窗口提供服务,所有顾客按到达时间排成一条长龙。当窗口空闲时,下一位顾客即去该窗口处理事务。此时如果已知第$i$位顾客与排在后面的第$j$位顾客是好朋友,并且愿意替朋友办理事务的话,那么第$i$位顾客的事务处理时间就是自己的事务加朋友的事务所耗时间的总和。在这种情况下,顾客的等待时间就可能被影响。假设所有人到达银行时,若没有空窗口,都会请求排在最前面的朋友帮忙(包括正在窗口接受服务的朋友);当有不止一位朋友请求某位顾客帮忙时,该顾客会根据自己朋友请求的顺序来依次处理事务。试编写程序模拟这种现象,并计算顾客的平均等待时间。

输入格式:

输入的第一行是两个整数:1≤$N$≤10000,为顾客总数;0≤$M$≤100,为彼此不相交的朋友圈子个数。若$M$非0,则此后$M$行,每行先给出正整数2≤$L$≤100,代表该圈子里朋友的总数,随后给出该朋友圈里的$L$位朋友的名字。名字由3个大写英文字母组成,名字间用1个空格分隔。最后$N$行给出$N$位顾客的姓名、到达时间$T$和事务处理时间$P$(以分钟为单位),之间用1个空格分隔。简单起见,这里假设顾客信息是按照到达时间先后顺序给出的(有并列时间的按照给出顺序排队),并且假设每个事务最多占用窗口服务60分钟(如果超过则按60分钟计算)。

输出格式:

按顾客接受服务的顺序输出顾客名字,每个名字占1行。最后一行输出所有顾客的平均等待时间,保留到小数点后1位。

输入样例:

1
2
3
4
5
6
7
8
9
6 2
3 ANN BOB JOE
2 JIM ZOE
JIM 0 20
BOB 0 15
ANN 0 30
AMY 0 2
ZOE 1 61
JOE 3 10

输出样例:

1
2
3
4
5
6
7
JIM
ZOE
BOB
ANN
JOE
AMY
75.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include<iostream>
#include<cstring>
#include<unordered_map>
#include<vector>
#include<algorithm>

using namespace std;

struct customer { //定义顾客结构体
char name[4];
int arriveTime, processTime;
};

int N, M;
unordered_map<string, int> friendMap, customerId; //friendMap存储每个人所属的朋友圈编号,customerId存储每个人名的到达顺序
bool visited[10000]; //visited[]数组标记第i个到达的人是否已经被处理过
vector<string> friends[100], result; //friends[i]存储朋友圈编号为i的朋友名,result存储结果

bool cmp(string s1, string s2);

int main() {
scanf("%d %d", &N, &M);
fill(visited, visited + N, false);
for(int i = 0; i < M; i++) {
int L;
scanf("%d", &L);
for(int j = 0; j < L; j++) {
char name[4];
scanf("%s", name);
friendMap[name] = i;
friends[i].push_back(name);
}
}
customer customers[N];
for(int i = 0; i < N; i++) {
char name[4];
scanf("%s %d %d", name, &customers[i].arriveTime, &customers[i].processTime);
if(customers[i].processTime > 60) { //如果单次处理时间超过60,当作60处理
customers[i].processTime = 60;
}
strcpy(customers[i].name, name);
customerId[name] = i;
}
int totalTime = 0; //总等待时间
int window = customers[0].arriveTime; //一开始的窗口时间应该设置为最先到达的顾客的到达时间
for(int i = 0; i < N; i++) {
if(visited[i]) { //如果该顾客已经被处理过了,则跳过本次循环
continue;
}
if(friendMap.find(customers[i].name) == friendMap.end()) { //如果该顾客不属于任何一个朋友圈
if(window > customers[i].arriveTime) { //如果窗口时间大于顾客的到达时间
totalTime += window - customers[i].arriveTime; //总等待时间增加
window += customers[i].processTime; //窗口时间加上该顾客的处理时间
}else{
window = customers[i].arriveTime + customers[i].processTime; //窗口时间更新为顾客的到达时间加上该顾客的处理时间
}
visited[i] = true;
result.push_back(customers[i].name);
continue; //跳过本次循环
}
int friendID = friendMap[customers[i].name];
sort(friends[friendID].begin(), friends[friendID].end(), cmp); //对该顾客所属朋友圈的朋友按到达顺序进行排序
for(int j = 0; j < friends[friendID].size(); j++) {
int id = customerId[friends[friendID][j]];
if(j > 0 && customers[id].arriveTime > window){ //如果下一个朋友的在window的空闲时间之前没有到达,则无法插队
break;
}
if(visited[id]){
continue;
}
if(window > customers[id].arriveTime) {
totalTime += window - customers[id].arriveTime;
window += customers[id].processTime;
} else {
window = customers[id].arriveTime + customers[id].processTime;
}
visited[id] = true;
result.push_back(friends[friendID][j]);
}
}
for(int i = 0; i < result.size(); i++) { //输出结果
printf("%s\n", result[i].c_str());
}
printf("%.1f\n", totalTime * 1.0 / N);
return 0;
}

bool cmp(string s1, string s2) {
return customerId[s1] < customerId[s2];
}
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×