模拟题。
这题第一个障碍是现在少见的循环电梯 ('pater-noster' elevator)
"The building has `pater-noster' elevator, i.e. elevator build up from several cabins running all around."
这种叫做 paster-noster 的电梯是 running all around 的,如动画所示,题目中费解的地方便清楚了。(欲知详情,请往维基百科)
第二个难点:模拟
模拟的核心是排队——等电梯或等房间
一开始可能感觉无从下手,模拟题的分析方法最主要的是分析事件。
准确地说,这道题有且仅有两个事件
排队等候(wating in queue)
行动(progress)
题目要求输出的是特工的活动记录(record)
solution:
1.用结构体表示事件:排队等候E,行动S
2.将电梯也看做房间编号是XX00
3.用优先队列维护排队等候的序列priority_queue<E, vector<E> > que,为此还需定义小于(<)运算符
bool operator < (const E& a, const E& b){ ...}
4.维护vector<S> record[26]:特工的行动序列
5.房间状态的维护
(1)room[11][11] :房间空闲的起始时刻,初始化为0,模拟过程中要不断更新
(2)updated[11][11]: updated[i][j]表示room[i][j]是否更新过
若当前等待事件的目标房间(或电梯)更新过,则要将当前等待事件再次入队
6.处理过程中时间统一化成秒,输出时再转化成指定的格式
7.其他细节见代码
网上见到的题解大多代码过长,可读性差,我自己写了个比较简明的版本,200行多一点
#include<bits/stdc++.h> using namespace std; typedef pair<int,int> P; int room[11][11]; //room[i][j]:房间空闲的起始时刻 bool updated[11][11]; //起始时刻是否已更新 vector<P> agent[26]; int time[26], sta[26]; int done[26];//已经访问的房间数目 struct S //行程 { int des; int cost; S(int des, int cost):des(des), cost(cost){} }; struct E //排队 { int code; int beg; int pos; E(int code, int beg, int pos):code(code), beg(beg), pos(pos){}; }; bool operator <(const E &a, const E &b) { //两人不是站在同一队列中等待 if(a.pos!=b.pos) return a.beg > b.beg; //两人同时到达 if(a.beg==b.beg) return a.code > b.code; int f=a.pos/100, r=a.pos%100; //等电梯 if(a.pos%100==0) { int t1=(a.beg%5?(a.beg/5+1)*5:a.beg); int t2=(b.beg%5?(b.beg/5+1)*5:b.beg); //两人乘同一班电梯,资历高的先进 if((t1<=room[f][r]&&t2<=room[f][r])||t1==t2) return a.code>b.code; return t1>t2; } else //等房间 { //两人都得等,资历高的先进 if(a.beg<=room[f][r]&&b.beg<=room[f][r]) return a.code>b.code; //!room[f][r]更新会影响这种比较 //至少有一个人不用等,先到的先进 else return a.beg > b.beg; } } priority_queue<E, vector<E> >que; //排队 vector<S> record[26]; //行程 void input() { FILE* fp=stdin; //提交时改成stdin char c; int h, m, s, pos, dur; while(fscanf(fp," %[A-Z] ",&c)) { int idx=c-'A'; fscanf(fp,"%d:%d:%d",&h,&m,&s); time[idx]=sta[idx]=3600*h+60*m+s; while(fscanf(fp,"%d",&pos),pos) { fscanf(fp,"%d",&dur); agent[idx].push_back(P(pos, dur)); } agent[idx].push_back(P(pos, 0)); //! Exit } } void init() { for(int i=0; i<26; i++) { if(!agent[i].size()) continue; if(agent[i][0].first/100==1) record[i].push_back(S(agent[i][0].first,30));//往一层某房间 else record[i].push_back(S(100,30));//往一层电梯 time[i]+=30; que.push(E(i,time[i],record[i].back().des)); } } void simulator() { int wait, id, cost, to, f, r; while(!que.empty()) { E e=que.top(); que.pop(); id=e.code; f=e.pos/100; r=e.pos%100; if(updated[f][r]) { que.push(e); updated[f][r]=false; continue; } if(r==0) //等电梯 { if(e.beg<=room[f][r]) wait=room[f][r]-e.beg; else wait=(e.beg%5? 5-e.beg%5: 0); if(wait) record[id].push_back(S(e.pos, wait)); time[id]+=wait; room[f][r]=time[id]+5; updated[f][r]=true; to=agent[id][done[id]].first; if(to==0) //!Exit { cost=30*(e.pos/100-1); record[id].push_back(S(100, cost)); record[id].push_back(S(to,30)); continue; } cost=30*(max(to/100,e.pos/100)-min(to/100,e.pos/100)); record[id].push_back(S(to/100*100, cost)); //在电梯里 time[id]+=cost; record[id].push_back(S(to, 10)); //往房间 time[id]+=10; que.push(E(id,time[id],to)); } else //等房间 { wait=max(room[f][r]-e.beg,0); if(wait) record[id].push_back(S(e.pos,wait)); time[id]+=wait; cost=agent[id][done[id]].second; record[id].push_back(S(-e.pos, cost)); //取反 time[id]+=cost; room[f][r]=time[id]; updated[f][r]=true; done[id]++; to=agent[id][done[id]].first; if(to==0&&f==1) //!Exit { record[id].push_back(S(to, 30)); continue; } if(to/100!=f) to=f*100; //需等电梯 record[id].push_back(S(to, 10)); //往电梯 time[id]+=10; que.push(E(id,time[id],to)); } } } void t_p(int t) { int h=t/3600, m=(t%3600)/60, s=t%3600%60; printf("%02d:%02d:%02d ",h,m,s); } void e_p(int pre, int cur) { if(pre==0) {printf("Entry\n"); return;} if(cur==0) {printf("Exit\n"); return;} if(cur<0) {printf("Stay in room %04d\n",-cur); return;} if(pre==cur) { if(cur%100==0) printf("Waiting in elevator queue\n"); else printf("Waiting in front of room %04d\n",cur); return; } if(pre%100==0&&cur%100==0) {printf("Stay in elevator\n"); return;}; if(pre<0) { if(cur%100==0) printf("Transfer from room %04d to elevator\n",-pre); else printf("Transfer from room %04d to room %04d\n",-pre, cur); return; } else printf("Transfer from elevator to room %04d\n",cur); } void output() { int pre_pos, cur_pos, t; for(int i=0; i<26; i++) { if(!record[i].size()) continue; t=sta[i]; pre_pos=0; printf("%c\n",'A'+i); for(int j=0; j!=record[i].size(); j++) { t_p(t); t_p(t+=record[i][j].cost); cur_pos=record[i][j].des; e_p(pre_pos, cur_pos); pre_pos=cur_pos; } printf("\n"); } } int main() { input(); init(); simulator(); output(); return 0; }