数据结构与算法题目集(中文)7-48 银行排队问题之单窗口“夹塞”版 (30分)(hash+数组的灵活应用)
1.题目
排队“夹塞”是引起大家强烈不满的行为,但是这种现象时常存在。在银行的单窗口排队问题中,假设银行只有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位。
输入样例:
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
输出样例:
JIM
ZOE
BOB
ANN
JOE
AMY
75.2
2.题目分析
circle[Hash(s)]=i+1;
3.代码
(参考https://blog.csdn.net/wuqi5328/article/details/83449834)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
typedef struct LNode {
int name;
int arrive;
int deal;
}LNode;
int circle[20000] = { 0 };
int Hash(char *str) {
return (str[0] - 65) * 26 * 26 + (str[1] - 65) * 26 + (str[2] - 65);
}
void print_name(int s) {
printf("%c%c%c\n", s / 26 / 26 + 65, s / 26 % 26 + 65, s % 26 + 65);
}
int main() {
int n, m;
scanf("%d %d", &n, &m);
LNode *p = (LNode*)malloc(sizeof(LNode)*n);
int head = 0, tail = 0;
int *book = (int*)malloc(sizeof(int)*n);
for (int i = 0; i<n; i++) book[i] = 0;
for (int i = 1; i <= m; i++)
{
int num; scanf("%d", &num);
while (num--)
{
char s[4];
scanf("%s", s);
circle[Hash(s)] = i + 1;//circle中的index是名字中hash函数的值,而对应数组的值则是i+1,即同一朋友圈中的人数组的值是一样的
}
}
for (int i = 0; i<n; i++)
{
char s[4];
scanf("%s %d %d", s, &p[i].arrive, &p[i].deal);
if (p[i].deal>60) p[i].deal = 60;
p[i].name = Hash(s);
}
int coun = 0;
book[0] = 1;
print_name(p[0].name);
int left, sum = 0;
left = p[0].arrive + p[0].deal;
coun++;
LNode front = p[0];
while (coun <= n)
{
//寻找下一个需要办理的人
int flag = 0;
for (int i = 0; i<n; i++)
{
if (book[i]) continue;
if (p[i].arrive>left) break;
if (circle[front.name] == circle[p[i].name]&& p[i].arrive <= left)
{
//printf("I find a friend and I can help him!\n");
flag = 1;
book[i] = 1;
print_name(p[i].name);
sum += left - p[i].arrive;
left += p[i].deal;
front = p[i];
break;
}
}
if (!flag)
{//按顺序进行查找,不插队
for (int i = 0; i<n; i++)
{
if (book[i]) continue;
//printf("I can not a friend,so I must find next one\n");
print_name(p[i].name);
book[i] = 1;
if (left <= p[i].arrive) sum += 0;
else sum += left - p[i].arrive;
if (p[i].arrive >= left) left = p[i].arrive;
left += p[i].deal;
front = p[i];
break;
}
}
coun++;
}
printf("%.1lf\n", (sum*1.0) / n);
}