pat1026Table Tennis (30)
題意分析:
(1)給出N個人到達乒乓球場的時間以及他們需要打多長時間的球,這些人分為兩類:一類是VIP客戶,一類是非VIP客戶,所有的客戶按到來的時間排好隊伍等候,一旦出現空的乒乓球檯,客戶將立即選擇編號最小的乒乓球檯,每個客戶最多不能超過兩個小時,求每個客戶的等待時間,以及每個乒乓球檯一天服務了多少人。
(2)VIP客戶與普通客戶不同點在於:一旦有VIP桌子空閒,處於等待佇列中的最早到達的VIP客戶(如果有的話)可以獲得使用權,而不管他前面是否有人在等待。
(3)如果沒有VIP客戶,當VIP卓空閒時,普通客戶也可使用。
(4)綜上所述,需要維護三個佇列:VIP客戶到達時間的序列、普通使用者到達時間的序列、每個桌子空閒的時刻,其中桌子的空閒時刻的計算跟1017題銀行視窗空閒時刻的計算一樣,大家可以去參考。
(5)這三個佇列的更新策略是:一旦有桌子空閒,在佇列中最早到達的人可以選擇序號最小的空閒的桌子使用;有以下情況例外:若此桌是VIP桌子,且佇列中有VIP等待客戶,那麼無論他前面是否還有等待的人,立即獲得使用權;還有若既有普通桌子和VIP桌子空閒,VIP客戶選擇VIP桌子
可能坑點:
這題難倒了不少人,題幹中有幾處沒有說明白(大坑!!!),其中也是巨坑連連。。。,總結起來有以下幾點需要注意:
(1)每個乒乓球檯的服務時間在8:00~21:00之間,超過21:00的不再服務
(2)等待佇列中,VIP的優先順序體現在當有空VIP專用球檯時,VIP客戶可以直接使用,而不管前面是否有普通客戶在等待
(3)最為重要的一點,當有普通球檯和VIP球檯時,VIP客戶遵循選擇最小編號的VIP球檯(VIP就要這麼任性),而非編號最小的球檯;普通客戶遵循選擇最小的球檯
(4)每個人的服務時間在2小時之內,超過2小時的按2小時處理;
(5)注意最後計算等待時間時採用的是四捨五入
#include <iostream> #include <algorithm> #include <string.h> #include <stdio.h> #include <vector> #include <limits.h> using namespace std; struct players { int arriveTime; int startServe; int serveTime; int waitTime; int isVIP; }; //等待佇列中的VIP客戶 vector<players >vipPlayers; //普通客戶 vector<players >ordinaryPlayers; //處理完輸出資訊的客戶 vector<players >total; struct tables { int VIP; int cnt; int vacantTime; }; tables t[101]; bool cmpPlayers(players a,players b) { return a.arriveTime<b.arriveTime; } bool cmpStartServe(players a,players b) { return a.startServe<b.startServe; } int main() { int N,K,M,i=0; cin>>N; int hh,mm,ss,wait,vip; players temp; while(i<N) { scanf("%d:%d:%d %d %d",&hh,&mm,&ss,&wait,&vip); temp.arriveTime=hh*3600+mm*60+ss; temp.serveTime=wait*60; temp.isVIP=vip; i++; if(temp.arriveTime>=3600*21)continue; if(vip==1)vipPlayers.push_back(temp); else ordinaryPlayers.push_back(temp); } cin>>K>>M; for(int j=1;j<=K;j++) { t[j].VIP=0; t[j].vacantTime=8*3600; t[j].cnt=0; } int tag; for(int j=0;j<M;j++) { cin>>tag; t[tag].VIP=1; } if(ordinaryPlayers.size()>0)sort(ordinaryPlayers.begin(),ordinaryPlayers.end(),cmpPlayers); if(vipPlayers.size()>0)sort(vipPlayers.begin(),vipPlayers.end(),cmpPlayers); while(ordinaryPlayers.size()>0||vipPlayers.size()>0) { int minVacant=INT_MAX; int minVipVacant=INT_MAX; int index; int vipIndex; for(int j=1;j<=K;j++) { if(t[j].vacantTime<minVacant) { minVacant=t[j].vacantTime; index=j; } if(t[j].VIP==1&&t[j].vacantTime<minVipVacant) { minVipVacant=t[j].vacantTime; vipIndex=j; } } if(t[index].vacantTime>=21*3600)break; players nextPlayers; if(vipPlayers.size()==0) { nextPlayers=ordinaryPlayers.front(); ordinaryPlayers.erase(ordinaryPlayers.begin()); } else if(ordinaryPlayers.size()==0) { nextPlayers=vipPlayers.front(); vipPlayers.erase(vipPlayers.begin()); } else { if(t[index].VIP==1) { if(vipPlayers.front().arriveTime<ordinaryPlayers.front().arriveTime||t[index].vacantTime>=vipPlayers.front().arriveTime) { nextPlayers=vipPlayers.front(); vipPlayers.erase(vipPlayers.begin()); } else { nextPlayers=ordinaryPlayers.front(); ordinaryPlayers.erase(ordinaryPlayers.begin()); } } else { if(vipPlayers.front().arriveTime<ordinaryPlayers.front().arriveTime) { nextPlayers=vipPlayers.front(); vipPlayers.erase(vipPlayers.begin()); } else { nextPlayers=ordinaryPlayers.front(); ordinaryPlayers.erase(ordinaryPlayers.begin()); } } } //控制每個人的時間在兩小時之內,超過兩小時按兩個小時截斷 if(nextPlayers.serveTime>7200)nextPlayers.serveTime=7200; //這裡需要記清楚:一旦有VIP桌子空閒,等待佇列中的VIP客戶就會選擇VIP桌子,不管是否有普通桌子空閒 if(nextPlayers.isVIP==1&&nextPlayers.arriveTime>=t[vipIndex].vacantTime) { nextPlayers.waitTime=0; nextPlayers.startServe=nextPlayers.arriveTime; t[vipIndex].vacantTime=nextPlayers.arriveTime+nextPlayers.serveTime; t[vipIndex].cnt++; } else { if(nextPlayers.arriveTime<=t[index].vacantTime) { nextPlayers.waitTime=t[index].vacantTime-nextPlayers.arriveTime; nextPlayers.startServe=t[index].vacantTime; t[index].vacantTime+=nextPlayers.serveTime; } else { nextPlayers.waitTime=0; nextPlayers.startServe=nextPlayers.arriveTime; t[index].vacantTime=nextPlayers.arriveTime+nextPlayers.serveTime; } t[index].cnt++; } total.push_back(nextPlayers); } sort(total.begin(),total.end(),cmpStartServe); for(int i=0;i<total.size();i++) { int waitMinutes=total[i].waitTime/60+(total[i].waitTime%60<30?0:1); printf("%02d:%02d:%02d %02d:%02d:%02d %d\n",total[i].arriveTime/3600, (total[i].arriveTime%3600)/60,total[i].arriveTime%60, total[i].startServe/3600,(total[i].startServe%3600)/60, total[i].startServe%60,waitMinutes); } int first=1; for(int i=1;i<=K;i++) { if(first)first=0; else cout<<" "; cout<<t[i].cnt; } return 0; }