排队“夹塞”是引起大家强烈不满的行为,但是这种现象时常存在。在银行的单窗口排队问题中,假设银行只有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
思路:
先使用并查集将朋友建树,然后在遍历的过程中找root相同的人,然后就是按照题意模拟,本来想的不适用stl,但是最后一个测试点超时,上网查了一下数据,的确最后一个测试点会卡时限,但是再写一个红黑树或哈希显然不太现实,所以等以后用stl写一下,目前的代码是只有最后一个测试点超时,目前分数27,满分代码以后再更。
#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<cmath>
#include<vector>
#include<cstdlib>
#include<cctype>
#include<queue>
#include<iomanip>
using namespace std;
const int INF=0xfffffff;
typedef long long ll;
const int maxn=10001;
struct peo
{
string name;
int l,r;
bool flag;
peo()
{
flag=false;
}
};
peo wirt[maxn];
string all_name[maxn];
int root[maxn];
string ans[maxn];
int all_cnt;
int find_root(string s)
{
int p=-1;
for(int i=0; i<all_cnt; i++)
{
if(all_name[i]==s)
{
p=i;
break;
}
}
if(p!=-1)
return root[p];
else
return p;
}
int main()
{
ios::sync_with_stdio(false);
int n,m;
cin>>n>>m;
int p=0;
int all_time=0;
all_cnt=0;
int all_wirt=0;
for(int i=0; i<m; i++)
{
int k;
cin>>k;
all_cnt+=k;
for(int j=p; j<p+k; j++)
{
cin>>all_name[j];
root[j]=p;
}
p=all_cnt;
}
peo w;
for(int i=0; i<n; i++)
{
cin>>w.name>>w.l>>w.r;
if(w.r>60)
w.r=60;
w.flag=false;
wirt[i]=w;
}
int cnt=0;
for(int i=0; i<n; i++)
{
if(wirt[i].flag)
continue;
else
{
ans[cnt]=wirt[i].name;
cnt++;
wirt[i].flag=true;
if(all_time>=wirt[i].l)
all_wirt+=all_time-wirt[i].l;
int k=i+1;
int q=find_root(wirt[i].name);
all_time=max(all_time,wirt[i].l);
all_time+=wirt[i].r;
while(k<n&&q!=-1)
{
if(find_root(wirt[k].name)!=-1&&find_root(wirt[k].name)==q&&all_time>=wirt[k].l)
{
all_wirt+=all_time-wirt[k].l;
wirt[k].flag=true;
all_time+=wirt[k].r;
ans[cnt]=wirt[k].name;
cnt++;
}
k++;
}
}
}
for(int i=0; i<cnt; i++)
cout<<ans[i]<<endl;
cout<<setprecision(1)<<fixed<<(double)all_wirt/(double)n<<endl;
}