#include<iostream>
#include<map>
#include<string>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;
int close_time=75600;
struct player{
int arrive_time;
int play_time;
int flag;
}P;
struct table{
int accT;
int flag;
table(){
accT=28800;
flag=0;
}
};
vector<player> usul_players;
vector<player> vip_player;
bool mycmp(player a,player b){
return a.arrive_time<b.arrive_time;
}
int main(){
int N;
scanf("%d",&N);
int h,m,s;
for(int i=0;i<N;++i){
scanf("%d:%d:%d %d %d",&h,&m,&s,&P.play_time,&P.flag);
if(P.play_time>120) P.play_time=120;
P.arrive_time=h*3600+m*60+s;
if(P.flag)
vip_player.push_back(P);
else
usul_players.push_back(P);
}
P.arrive_time=1e8;
vip_player.push_back(P);
usul_players.push_back(P);
sort(usul_players.begin(),usul_players.end(),mycmp);
sort(vip_player.begin(),vip_player.end(),mycmp);
int K,M;
scanf("%d%d",&K,&M);
table tables[101];
for(int i=0;i<M;++i){
int table_num;
scanf("%d",&table_num);
tables[table_num].flag=1;
}
int serve_num[101]={0};
int cnt=0;
while(cnt<N){
int cus_idx,table_idx=-1;
//选人;
cus_idx=vip_player[0].arrive_time<usul_players[0].arrive_time?1:0;
if(cus_idx==1){
for(int i=1;i<=K;++i)
if(tables[i].accT<=vip_player[0].arrive_time)
if(tables[i].flag==1){
table_idx=i;
break;
}else if(table_idx==-1) table_idx=i;
if(table_idx==-1){ //无可用的桌子;
table_idx=1;
for(int i=2;i<=K;++i)
if(tables[i].accT<tables[table_idx].accT) table_idx=i;
else if(tables[i].accT==tables[table_idx].accT&&tables[i].flag>tables[table_idx].flag) table_idx=i;
}
}else{
for(int i=1;i<=K;++i)
if(tables[i].accT<=usul_players[0].arrive_time){
table_idx=i;
break;
}
if(table_idx==-1){
table_idx=1;
for(int i=2;i<=K;++i)
if(tables[i].accT<tables[table_idx].accT) table_idx=i;
// else if(tables[i].accT==tables[table_idx].accT&&tables[i].flag<tables[table_idx].flag) table_idx=i;
//如果出现普通客户当前没有可用的球桌,寻找最早可用球桌的过程中,有一个vip球桌和一个普通球桌在未来的同一个时间点可用,而且,这个可用的vip球桌可用时有vip客户在等候,到底是先打印普通客户,还是先打印vip客户?
if(tables[table_idx].flag==1&&vip_player[0].arrive_time<=tables[table_idx].accT)
cus_idx=1;
}
}
P=cus_idx==0?usul_players[0]:vip_player[0];
int serve_p=max(tables[table_idx].accT,P.arrive_time);
if(serve_p>=close_time) break;
++serve_num[table_idx];
printf("%02d:%02d:%02d %02d:%02d:%02d %.0lf\n",P.arrive_time/3600,P.arrive_time/60%60,P.arrive_time%60,serve_p/3600,serve_p/60%60,serve_p%60,round((serve_p-P.arrive_time)/60.0));
tables[table_idx].accT=serve_p+P.play_time*60;
if(cus_idx==0) usul_players.erase(usul_players.begin());
else vip_player.erase(vip_player.begin());
++cnt;
}//while(非空);
for(int i=1;i<=K;++i){
printf("%d",serve_num[i]);
if(i<K)
printf(" ");
}
system("pause");
return 0;
}
总体思路:
1、将客户分为VIP客户队和普通客户队,然后在两种队后各添加一个到达时间为1e8的虚拟客户,防止出现队空的情况,简化讨论情形。
2、判断两个队首的客户中,那个客户更早到来·:
a、如果是VIP客户更早到来,再分为两种情况讨论:
如果客户到来时有空余的桌子,那么如果该桌子为VIP桌,那就选择最小的空闲VIP,否则,选择最小的普通桌;
否则,客户到来时没有空桌子,客户需要等候,那就选择最早可获得的 且编号最小的任意桌。
b、同理,当普通客户更早到来时,也要分为两种情形讨论:
如果客户到来时有空余桌,选择编号最小的可用任意桌(即使是VIP桌也无所谓,因为既然桌子可用,那桌子open的时间就在该普通客户到来之前,而普通客户又比后面的客户早,所以VIP桌可用时,可以保证没有VIP客户等候);
否则·,客户到来时没有空桌,客户等候,选择最早可获得的桌子,如果是普通桌,那就等候该普通桌open,普通客户使用,如果是·VIP桌先open,那就要判断一下VIP桌可用时,是否有VIP客户在等候,如果是的话,那VIP客户要先被服务,否则VIP桌才能被这个普通客户使用。(关于此处,还有个点比较模糊,如果最早可得的桌子有两个,一个是VIP桌,一个是普通桌,且VIP桌可用时队列中有VIP客户在等候,那到底是先输出普通客户的使用时间,还是VIP客户的使用时间?PS:我题目中是有VIP桌最先可用,特判VIP客户,先输出的VIP)
3、注意的点:题目说没在21:00前被服务的都不能服务,所以在while()循环中途退出的条件要写为判断服务时间serve_time>=21:00时break;不能是桌子可用时间>=21:00,防止出现21:00到来的客户,因为虽然有时桌子可用,但是没有客户。