7-6 银行排队问题之单队列多窗口加VIP服务 (30 分)
假设银行有K个窗口提供服务,窗口前设一条黄线,所有顾客按到达时间在黄线后排成一条长龙。当有窗口空闲时,下一位顾客即去该窗口处理事务。当有多个窗口可选择时,假设顾客总是选择编号最小的窗口。
有些银行会给VIP客户以各种优惠服务,例如专门开辟VIP窗口。为了最大限度地利用资源,VIP窗口的服务机制定义为:当队列中没有VIP客户时,该窗口为普通顾客服务;当该窗口空闲并且队列中有VIP客户在等待时,排在最前面的VIP客户享受该窗口的服务。同时,当轮到某VIP客户出列时,若VIP窗口非空,该客户可以选择空闲的普通窗口;否则一定选择VIP窗口。
本题要求输出前来等待服务的N位顾客的平均等待时间、最长等待时间、最后完成时间,并且统计每个窗口服务了多少名顾客。
输入格式:
输入第1行给出正整数N(≤1000),为顾客总人数;随后N行,每行给出一位顾客的到达时间T
、事务处理时间P
和是否VIP的标志(1是VIP,0则不是),并且假设输入数据已经按到达时间先后排好了顺序;最后一行给出正整数K(≤10)—— 为开设的营业窗口数,以及VIP窗口的编号(从0到K−1)。这里假设每位顾客事务被处理的最长时间为60分钟。
输出格式:
在第一行中输出平均等待时间(输出到小数点后1位)、最长等待时间、最后完成时间,之间用1个空格分隔,行末不能有多余空格。
在第二行中按编号递增顺序输出每个窗口服务了多少名顾客,数字之间用1个空格分隔,行末不能有多余空格。
输入样例:
10
0 20 0
0 20 0
1 68 1
1 12 1
2 15 0
2 10 0
3 15 1
10 12 1
30 15 0
62 5 1
3 1
输出样例:
15.1 35 67
4 5 1
#define FRER() freopen("in.txt","r",stdin)
#define FREW() freopen("out.txt","w",stdout)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#include <stack>
#include <set>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
struct window{
int cnt;
int t;
window(){
cnt = t = 0;
}
}w[17];
struct person{
int id;
int vip;
int c,p;
int vis;
person(){
c = p = vip = vis = 0;
}
}p[1007];
queue<person>q;
int main(){
int n,k,vip;
int tot_time,max_time,last_time;
tot_time = max_time = last_time = 0;
cin>>n;
int l=1,r=n;
for(int i=1;i<=n;i++){
cin>>p[i].c>>p[i].p>>p[i].vip;
p[i].p=p[i].p>60?60:p[i].p;
p[i].id = i;
if(p[i].vip){
q.push(p[i]);
}
}
cin>>k>>vip;vip++;
while(l<=r){
person& now = p[l];
if(now.vis){l++;continue;}
//cout<<l<<endl;
bool flag = false;
if(now.vip){
if(w[vip].t<=now.c){
w[vip].cnt++;
w[vip].t = now.c+now.p;
p[now.id].vis = 1;
l++;
q.pop();
flag = true;
}
}
if(!flag){
bool sign = false;
int ppos=0;
for(int j=1;j<=k;j++){
if(w[j].t<=now.c){
sign = true;
ppos = j;
break;
}
}
if(sign){
bool flag2 = false;
if(ppos==vip&&!q.empty()){
person v = q.front();
if(v.c==p[l].c){
flag2 = true;
w[ppos].cnt++;
w[ppos].t=v.p+v.c;
p[v.id].vis = 1;
q.pop();
if(v.id==p[l].id)l++;
}
}if(!flag2){
w[ppos].t = p[l].c+p[l].p;
w[ppos].cnt++;
p[l].vis = 1;
if(!q.empty()&&q.front().id==l){
q.pop();
}
l++;
}
}
if(!sign){
int min = 99999999;
int pos = 0;
for(int j=1;j<=k;j++){
if(w[j].t<min){
min = w[j].t;
pos = j;
}
}
bool flag3 = false;
if(!q.empty()&&q.front().c<=min){
person v = q.front();
if(vip==pos){
p[v.id].vis = 1;
tot_time += min - v.c;
w[pos].t += v.p;
w[pos].cnt++;
flag3 =true;
q.pop();
max_time = max(max_time,min-v.c);
}else if(w[vip].t==min){
flag3 = true;
p[v.id].vis = 1;
tot_time += min - v.c;
w[vip].t += v.p;
w[vip].cnt++;
q.pop();
if(v.id==l) l++;
max_time = max(max_time,min-v.c);
}
}
if(!flag3){
if(p[l].vip) q.pop();
tot_time += min - p[l].c;
w[pos].t += p[l].p;
w[pos].cnt++;
max_time = max(max_time,min-p[l].c);
l++;
}
}
}
}
for(int i=1;i<=k;i++) last_time = max(last_time,w[i].t);
printf("%.1f %d %d\n",1.0*tot_time/n,max_time,last_time);
for(int i=1;i<=k;i++){
printf("%d%c",w[i].cnt,i==k?'\n':' ');
}
}