题目大意:排队“夹塞”是引起大家强烈不满的行为,但是这种现象时常存在。在银行的单窗口排队问题中,假设银行只有1个窗口提供服务,所有顾客按到达时间排成一条长龙。当窗口空闲时,下一位顾客即去该窗口处理事务。此时如果已知第i位顾客与排在后面的第j位顾客是好朋友,并且愿意替朋友办理事务的话,那么第i位顾客的事务处理时间就是自己的事务加朋友的事务所耗时间的总和。在这种情况下,顾客的等待时间就可能被影响。假设所有人到达银行时,若没有空窗口,都会请求排在最前面的朋友帮忙(包括正在窗口接受服务的朋友);当有不止一位朋友请求某位顾客帮忙时,该顾客会根据自己朋友请求的顺序来依次处理事务。试编写程序模拟这种现象,并计算顾客的平均等待时间。
一道模拟题,首先要里明白自己的思路,否则这道题会很难通过。
在这里说一点自己被坑的地方: 两人虽然同属一个圈子,但可能第一个人办完业务后,第二个人还没有达到,所以就不再考虑第二个人,让他去老老实实排队;
下面给出AC代码,附带一些必要的注释:
#include <bits/stdc++.h>
using namespace std;
const int maxn=10000+10;
struct node
{
string name;
int arrive,work;
}que[maxn];
int main()
{
int n,m; cin>>n>>m;
vector<string> friends[maxn];
map<string, int> number; //记录每个圈子都有谁,vector的一维坐标代表第几个圈子
for(int i=1;i<=m;i++)
{
int num; cin>>num;
for(int j=0;j<num;j++)
{
string s; cin>>s;
number[s]=i;
friends[i].push_back(s);
}
}
map<string,int> norder;//读入正常的顺序;
for(int i=1;i<=n;i++)
{
string s; int a,b; cin>>s>>a>>b;
que[i].name=s,que[i].arrive=a,que[i].work= b>=60? 60 : b;
norder[s]=i;
}
vector<int> reorder[maxn];//记录每个圈子里各个人的先后顺序
for(int i=1;i<=m;i++)
{
for(int j=0;j<friends[i].size();j++)
{
int x=norder[friends[i][j]];
reorder[i].push_back(x);
}
sort(reorder[i].begin(),reorder[i].end());
}
bool vis[maxn]; memset(vis,false,sizeof(vis));
int time=0,ans=0;
for(int i=1;i<=n;i++)
{
if(vis[i]==true) continue;
vis[i]=true;
cout<<que[i].name<<endl;
if(que[i].arrive>=time) time=que[i].work+que[i].arrive;
else
{
ans+=time-que[i].arrive;
time+=que[i].work;
}
int x=number[que[i].name];
for(int j=0;j<reorder[x].size();j++)
{
int t=reorder[x][j];
if(vis[t]==true) continue;
if(que[t].arrive<=time)//如果一个圈子 第一个人办完了第二个人没到,就不进行考虑
{
vis[t]=true;
ans+=time-que[t].arrive;
time+=que[t].work;
cout<<que[t].name<<endl;
}
}
}
printf("%.1f",ans*1.0/n);
return 0;
}