Table Tennis
这是一道较复杂的队列问题,但仍符合送客入队迎客三步,只不过迎客时优先处理vip桌迎客
解答:
教训:初值一定不要乱定,在一开始做本题的时候,对table中的serve(服务标志位)初始化为0,然而顾客编号中也有0,导致0号顾客一直停留在桌上,后果可想而知,,,
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
struct player{
int come_time,play_time,leave_time=0,serve_time=0;//serve_time为开始服务的时间
int isvip=0;// 0/1->否/是
}p[10001];
struct table{
int count=0,serve=-1,isvip=0;
}t[101];
vector<int> book;//因为vip和普通用户服务顺序混合,所以需要一个book来存放服务顺序
bool comp(player p1,player p2){
return p1.come_time<p2.come_time;
}
void printtime(int Time){
printf("%02d:%02d:%02d ",Time/3600,Time%3600/60,Time%60); //eg:3661
}
int main(){
int N,i,j;
cin>>N;
//数据的读入
for(i=0;i<N;i++){
int hh,mm,ss;
char c;
cin>>hh>>c>>mm>>c>>ss>>p[i].play_time>>p[i].isvip;
p[i].come_time=hh*3600+mm*60+ss;
p[i].play_time=p[i].play_time*60;
if(p[i].play_time>7200) p[i].play_time=7200;
}
int K,M;//K->总桌数,M->vip桌数
cin>>K>>M;
for(i=1;i<=M;i++){//vip信息读入
cin>>j;
t[j].isvip=1;
}
sort(p,p+N,comp);//按照come_time排序
queue<int> q1,q2;//q1,q2分别入队普通用户与vip用户
int cursor=0;//p中入队遍历光标
for(int Time=28800;Time<75600;Time++){
//送客
for(i=1;i<=K;i++){
if(t[i].serve>=0){
j=t[i].serve;
if(p[j].leave_time==Time) t[i].serve=-1;
}
}
//入队
while(cursor<N&&p[cursor].come_time==Time){//合法下标&&客户来了(时间到了)
q1.push(cursor);//入队普通队列
if(p[cursor].isvip) q2.push(cursor);//如果是vip,入队vip队列
cursor++;
}
//vip桌迎客
//为vip队列分桌前,要清除队列q2已经在普通桌得到服务的vip用户,防止重复分桌
while(q2.size()&&p[q2.front()].serve_time!=0) q2.pop();
for(i=1;i<=K;i++){
if(!t[i].isvip) continue;//如果不是vip桌,跳过本桌
if(t[i].serve<0){//如果vip桌空着没人打
if(q2.size()){
int j=q2.front();
book.emplace_back(j);//记录服务顺序
t[i].serve=j;
t[i].count++;
p[j].serve_time=Time;
p[j].leave_time=Time+p[j].play_time;
q2.pop();
}
}
}
//为普通队列分桌前,要清除队列q1已经得到服务的普通用户与vip用户(普通队列既有vip用户又有普通用户),防止重复分桌
while(q1.size()&&p[q1.front()].serve_time!=0) q1.pop();
for(i=1;i<=K;i++){
if(t[i].serve<0){
if(q1.size()){
int j=q1.front();
book.emplace_back(j);//记录服务顺序
t[i].serve=j;
t[i].count++;
p[j].serve_time=Time;
p[j].leave_time=Time+p[j].play_time;
q1.pop();
}
}
}
}
for(int each:book){
printtime(p[each].come_time);
printtime(p[each].serve_time);
cout<<(p[each].serve_time-p[each].come_time+30)/60;//30+向上取整
cout<<endl;
}
cout<<t[1].count;
for(i=2;i<=K;i++) cout<<' '<<t[i].count;
return 0;
}//因为来的人不一定得到服务,排在前面的人不一定先得到服务(会员),所以考虑用vector来存放得到服务的人