PAT (Advenced Level) 1026. Table Tennis (30) 模拟排队,有vip

来源:互联网 发布:手机游戏服务端源码 编辑:程序博客网 时间:2024/06/07 00:15

A table tennis club has N tables available to the public. The tables are numbered from 1 to N. For any pair of players, if there are some tables open when they arrive, they will be assigned to the available table with the smallest number. If all the tables are occupied, they will have to wait in a queue. It is assumed that every pair of players can play for at most 2 hours.

Your job is to count for everyone in queue their waiting time, and for each table the number of players it has served for the day.

One thing that makes this procedure a bit complicated is that the club reserves some tables for their VIP members. When a VIP table is open, the first VIP pair in the queue will have the priviledge to take it. However, if there is no VIP in the queue, the next pair of players can take it. On the other hand, if when it is the turn of a VIP pair, yet no VIP table is available, they can be assigned as any ordinary players.

Input Specification:

Each input file contains one test case. For each case, the first line contains an integer N (<=10000) - the total number of pairs of players. Then N lines follow, each contains 2 times and a VIP tag: HH:MM:SS - the arriving time, P - the playing time in minutes of a pair of players, and tag - which is 1 if they hold a VIP card, or 0 if not. It is guaranteed that the arriving time is between 08:00:00 and 21:00:00 while the club is open. It is assumed that no two customers arrives at the same time. Following the players' info, there are 2 positive integers: K (<=100) - the number of tables, and M (< K) - the number of VIP tables. The last line contains M table numbers.

Output Specification:

For each test case, first print the arriving time, serving time and the waiting time for each pair of players in the format shown by the sample. Then print in a line the number of players served by each table. Notice that the output must be listed in chronological order of the serving time. The waiting time must be rounded up to an integer minute(s). If one cannot get a table before the closing time, their information must NOT be printed.

Sample Input:
920:52:00 10 008:00:00 20 008:02:00 30 020:51:00 10 008:10:00 5 008:12:00 10 120:50:00 10 008:01:30 15 120:53:00 10 13 12
Sample Output:
08:00:00 08:00:00 008:01:30 08:01:30 008:02:00 08:02:00 008:12:00 08:16:30 508:10:00 08:20:00 1020:50:00 20:50:00 020:51:00 20:51:00 020:52:00 20:52:00 03 3 2
模拟排队,这次比前面题1017的情况要复杂得多.
维护一个顾客数组和一个桌子数组,具体数据结构见代码。
先按照到达时间的先后顺序对顾客进行排序。
处理的主体是顾客数组。每次找到最快能空出来的桌子,若同时空出来,选最小序号,若空出来的时间超过21点,则后续顾客不再处理。用桌子空出来的时间将顾客数组分成两段,前面一段表示此时已经到达俱乐部的顾客。若空出来的桌子是vip桌,寻找此时已到达俱乐部的vip,插队到队伍最前面(直接插入排序)。对队首顾客进行处理时,若该顾客是vip,且空出的桌子不是vip桌,则判断该vip顾客到达时是否有vip桌空出来,若有则选取最小序号的(这是一个坑)。剩下的就是注意每个顾客最多只能玩2个小时,还有注意输出等待时间时的四舍五入。
/*2015.7.22cyq*/#include <iostream>#include <vector>#include <string>#include <algorithm>#include <fstream>using namespace std;//ifstream fin("case1.txt");//#define cin finstruct player{int arrive;//到达时间int start;//开始打球时间int process;        //打球持续时间int leave;//离开时间bool vip;//是否vip顾客bool operator < (const player &a)const{//用于按到达时间排序return arrive<a.arrive;}};struct table{int time;//可以使用的时间,初始化为8点bool isVip;//是否为vip桌int count;//服务次数table():time(28800),isVip(false),count(0){}};int timeToInt(const string &s){int sum=0;sum+=(s[0]-'0')*10+s[1]-'0';sum=sum*60+(s[3]-'0')*10+s[4]-'0';sum=sum*60+(s[6]-'0')*10+s[7]-'0';return sum;}int main(){int N;cin>>N;vector<player> wait(N);string a;int b;for(int i=0;i<N;i++){cin>>a>>b>>wait[i].vip;wait[i].arrive=timeToInt(a);wait[i].process=b*60;}sort(wait.begin(),wait.end());//按照到达时间排序int K,M;cin>>K>>M;vector<table> tables(K+1);//0号不用int x;for(int i=0;i<M;i++){cin>>x;tables[x].isVip=true;}int quickTime;int quickTable;int index=0;  for(int i=0;i<N;i++){//i号顾客quickTime=2147483647;for(int j=1;j<=K;j++){//最快结束的最小序号桌子if(tables[j].time<quickTime){quickTime=tables[j].time;quickTable=j;}}if(quickTime>=21*60*60||wait[i].arrive>=21*60*60){//超过21点wait.resize(i);break;    }//以quickTime将队伍分成两段,前面一段此时在俱乐部内while(index<N&&wait[index].arrive<=quickTime)index++;if(tables[quickTable].isVip){//空出来的是vip桌子int vipPos=i;//标记此时俱乐部内队伍中最早来的vip位置for(int j=i;j<index;j++){if(wait[j].vip){vipPos=j;break;}}player tmp=wait[vipPos];for(int j=vipPos-1;j>=i;j--)wait[j+1]=wait[j];wait[i]=tmp;//vip插队到最前面}//对队首顾客进行处理if(wait[i].vip){//是个vip顾客if(!tables[quickTable].isVip){//空出的不是vip桌//寻找arrive时最小的vip桌for(int y=1;y<=K;y++){if(tables[y].isVip&&tables[y].time<=wait[i].arrive){quickTable=y;break;}}}}wait[i].start=max(tables[quickTable].time,wait[i].arrive);if(wait[i].process>7200)//大于两个小时wait[i].process=7200;wait[i].leave=wait[i].start+wait[i].process;tables[quickTable].time=wait[i].leave;tables[quickTable].count++;}for(auto it=wait.begin();it!=wait.end();it++){int t1=(*it).arrive;int t2=(*it).start;printf("%02d:%02d:%02d",t1/3600,t1%3600/60,t1%60);printf(" %02d:%02d:%02d",t2/3600,t2%3600/60,t2%60);printf(" %d\n",(t2-t1+30)/60);//四舍五入}cout<<tables[1].count;for(int i=2;i<=K;i++)cout<<" "<<tables[i].count;return 0;}


                                             
0 0
原创粉丝点击