排队“夹塞”是引起大家强烈不满的行为,但是这种现象时常存在。在银行的单窗口排队问题中,假设银行只有1个窗口提供服务,所有顾客按到达时间排成一条长龙。当窗口空闲时,下一位顾客即去该窗口处理事务。此时如果已知第i位顾客与排在后面的第j位顾客是好朋友,并且愿意替朋友办理事务的话,那么第i位顾客的事务处理时间就是自己的事务加朋友的事务所耗时间的总和。在这种情况下,顾客的等待时间就可能被影响。假设所有人到达银行时,若没有空窗口,都会请求排在最前面的朋友帮忙(包括正在窗口接受服务的朋友);当有不止一位朋友请求某位顾客帮忙时,该顾客会根据自己朋友请求的顺序来依次处理事务。试编写程序模拟这种现象,并计算顾客的平均等待时间。
输入格式:
输入的第一行是两个整数:1,为顾客总数;0,为彼此不相交的朋友圈子个数。若M非0,则此后M行,每行先给出正整数2,代表该圈子里朋友的总数,随后给出该朋友圈里的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
代码:
#include <cstdio> #include <queue> #include <map> using namespace std; struct peo { char name[4]; int T,P; }p[10000]; int ans[10000],c; int n,m,l,num,ptime; double w; int f[10001],vis[10001]; char name[4]; map<string,int> mp; int main() { scanf("%d%d",&n,&m); while(m --) { scanf("%d",&l); for(int i = 0;i < l;i ++) { scanf("%s",name); f[mp[name] = ++ num] = m + 1;//由于不同圈子没有交集 所以不用并查集 用数组标记是否是同一个圈子 } } for(int i = 0;i < n;i ++) { scanf("%s%d%d",p[i].name,&p[i].T,&p[i].P); if(p[i].P > 60) p[i].P = 60; } int i = 0; while(i < n) { while(i < n && vis[i]) i ++; int d = f[mp[p[i].name]],j = i; if(i >= n) break; do {//这里这个循环是这样的 如果说第一个人在办理业务 后边有朋友 可以同时帮着办了 所谓等待时间就是从到达到自己的业务被着手处理等的时间 只要第一个人还在办理 后边来的朋友都可以交给他处理 除非他走了 if(vis[j] || f[mp[p[j].name]] != d) { j ++; continue; } w += max(0,ptime - p[j].T); ans[c ++] = j; ptime = max(ptime,p[j].T) + p[j].P; vis[j ++] = 1; } while(d && j < n && p[j].T <= ptime); } for(int i = 0;i < n;i ++) { printf("%s ",p[ans[i]].name); } printf("%.1f",w / n); }