/*************************
题意:
有一堆台球桌,和一堆赶来排队的人
每当有一个台球桌开放,队头的人就去使用
如果此时有一个VIP桌开放
队中的VIP可以马上使用,不用理会队伍里的其他人。
计算入队时间、开始时间、等待时间
并计算每个桌子服务的人数。
/************************
求解要点和注意点:
实现思路:
先把所有顾客按到达时间排序
接着分成vip队列和普通队列,都插进去。
然后每次选出一个空余时间最早的台球桌
如果有一个VIP桌的空余时间也是最早,同时这个桌子不会被普通顾客抢占
则我们选择这个VIP桌,而不是序号小的普通桌
接着再判断我们应该选择普通人还是VIP人来玩这个桌子
并计算这个桌子下一次的空余时间
坑点:
1.每个人最多玩2个小时,即使他们想玩更久也不行。
2.开放时间为8:00到21:00, 21:00以及21:00之后场馆的球桌不再接收新的人来玩。
注意是21:00及之后不能开新局,但21:00之前开的局是没事的。
3.顾客的进场时间可以刚好是21:00.
3.★当某一刻,同时开放了普通桌1和VIP桌3,而队伍中又正好有VIP
则VIP会直接选择3号桌而不是1号桌。
4.等待时间是四舍五入而不是向上取整。
************************/
/***********************
笔记:
*********************/
#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<queue>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
using namespace std;
#define M 10010
#define INF 0x7fffffff
struct player{
int h,m,s,begint;
int ut;
bool operator<(player b)const {
return begint > b.begint;
}
};
int fvip[105];
int main(){
int n,i,h,m,s,k,ut,vip;
priority_queue<struct player> q, vipq;
scanf("%d",&n);
struct player p;
for(i=0;i<n;i++){
scanf("%d:%d:%d%d%d",&h,&m,&s,&ut,&vip);
if(ut>120)
ut = 120;
p.h=h;p.m=m;p.s=s;p.ut=ut*60;
p.begint=h * 3600 + m * 60 + s;
if(vip){
vipq.push(p);
}
else q.push(p);
}
int vipn;
scanf("%d%d",&k,&vipn);
memset(fvip,0,sizeof(fvip));
int vipi;
for(i=0;i<vipn;i++){
scanf("%d",&vipi);
fvip[vipi]=1;
}
int tmin,select;
int outt[105],ans[105];
for(i=1;i<=k+1;i++){
outt[i]=8*3600;
ans[i]=0;
}
int waitt;
while( !(q.empty()&&vipq.empty()) ){
tmin = INF;
for(i = 1;i <=k; i++){
if(outt[i] < tmin){
tmin=outt[i];
select=i;
}else if(outt[i] == tmin)
if((!vipq.empty() ) && (vipq.top().begint<tmin || q.empty() || vipq.top().begint < q.top().begint) &&
(!fvip[select]) && fvip[i] ){
select = i;
}
}
//选q和vipq中最小的那个
if(q.empty()){p=vipq.top();vipq.pop();}
else if(vipq.empty()) {p=q.top();q.pop();}
else if(fvip[select] && vipq.top().begint <= tmin){
p=vipq.top();vipq.pop();
}
else if(q.top().begint < vipq.top().begint) {
p=q.top();q.pop();
}
else {
p=vipq.top();vipq.pop();
}
if( tmin > p.begint){
waitt=tmin-p.begint;
outt[select] = tmin + p.ut;
}
else{
waitt=0;
tmin = p.begint;
outt[select] = p.begint + p.ut;
}
if(tmin >= 21*3600)
break;
ans[select]++;
printf("%02d:%02d:%02d ",p.h,p.m,p.s);
printf("%02d:%02d:%02d ",tmin/3600,(tmin/60)%60,tmin%60);
waitt = waitt/60 +(waitt%60<30?0:1);
printf("%d\n",waitt);
}
for(i=1;i<=k;i++){
if(i != k)
printf("%d ",ans[i]);
else printf("%d\n",ans[i]);
}
return 0;
}
PAT 1026. Table Tennis (30) 队列模拟与特殊情况处理
最新推荐文章于 2022-05-15 10:34:19 发布