POJ1025 Department

题目来源:http://poj.org/problem?id=1025

题目大意:

  有一些特工,在一天里要访问一座大楼。这座大楼里有10层,每层10个房间(按xxyy编号每个房间,xx为楼层,yy为房间号)和1个电梯。每个特工要按顺序访问一些特定的房间,并在各个房间里待一段时间。每个特工在一天的某个时间点到达大楼的1层,然后需要30s的时间进行登记之类的活动。到达30s后可以到达一楼的电梯或到达他想要去的位于1楼的房间门口。大楼的电梯每5s一班,每上升一层或下降一层需要30s。出于安全考虑,每个房间和每层的电梯都同时只运行一个人在内。当有多人在电梯或房间门口需要进入时需要排队。每个特工都有一个唯一的编号(A->Z),编号越小,优先级越高,排队时优先。特工访问完一个房间去往下一个房间的过程中可能需要以下动作:从楼层的一个房间去往该层的另一个房间;从楼层的一个房间去往电梯->(等待电梯)->乘电梯->电梯去往另一层的某房间。当访问完所有需要访问的房间后,若特工在1层,则花30s办理手续,离开。若不在1层,则先下电梯至1层再办手续离开。一个特工一天只访问大楼一次,一天内所有活动都会完成。

各种动作需要的时间总结如下:

Entry:登记->到达1楼电梯或1楼某房间  30s

Exit:从最后一个房间或电梯出来至离开  30s

同一层,出电梯到达某房间(或进等候队列)或出房间到达电梯或出房间到到达另一房间  10s

从一层到另一层成电梯每上一层或下一层需要时间  30s

写一个程序来安排所有特工的活动。

输入:含有n>=0个不同的特工。首先输入该特工的编号,然后是进入大楼的时间。接下来的每行,前四个字符表示要访问的房间号码,后一个整数为该特工要在这个房间停留的时间。以0表示该特工的访问计划输入完毕。以"."表示所有输入结束。

输出:输出每个特工的编号加活动详细安排。


Sample Input

A 10:00:00
0101 100
0110 50
0202 90
0205 50
0
B 10:01:00
0105 100
0201 5
0205 200
0
.

Sample Output

A
10:00:00 10:00:30 Entry
10:00:30 10:02:10 Stay in room 0101
10:02:10 10:02:20 Transfer from room 0101 to room 0110
10:02:20 10:03:10 Stay in room 0110
10:03:10 10:03:20 Transfer from room 0110 to elevator
10:03:20 10:03:50 Stay in elevator
10:03:50 10:04:00 Transfer from elevator to room 0202
10:04:00 10:05:30 Stay in room 0202
10:05:30 10:05:40 Transfer from room 0202 to room 0205
10:05:40 10:07:40 Waiting in front of room 0205
10:07:40 10:08:30 Stay in room 0205
10:08:30 10:08:40 Transfer from room 0205 to elevator
10:08:40 10:09:10 Stay in elevator
10:09:10 10:09:40 Exit

B
10:01:00 10:01:30 Entry
10:01:30 10:03:10 Stay in room 0105
10:03:10 10:03:20 Transfer from room 0105 to elevator
10:03:20 10:03:25 Waiting in elevator queue
10:03:25 10:03:55 Stay in elevator
10:03:55 10:04:05 Transfer from elevator to room 0201
10:04:05 10:04:10 Stay in room 0201
10:04:10 10:04:20 Transfer from room 0201 to room 0205
10:04:20 10:07:40 Stay in room 0205
10:07:40 10:07:50 Transfer from room 0205 to elevator
10:07:50 10:08:20 Stay in elevator
10:08:20 10:08:50 Exit

本题是一道很复杂模拟题,虽然不必很复杂的算法设计,但是代码量很大,需要精心的设计,也是参考了别人的实现。

定义一个枚举类型表示每个特工当前所处的状态。

enum Event {
  et_entry, et_wait_elevator, et_wait_room, et_room2room, et_elevator2room,
  et_room2elevator, et_in_room, et_in_elevator, et_exit
};

把电梯看做一个特殊的房间,给予编号XX00。

为每一个房间准备一个等候队列,保存某时刻该房间的等候的特工。

每秒钟遍历每个特工和每个房间,更新特工、房间、电梯的状态。(每次到达电梯口或房间门口就将特工插入对应的等待队列,即使不需要等待,因为只要在输出时过滤掉等待0秒的过程即可。当房间或电梯可以让人进入时选择队列中优先级最高的让其进入。)具体见代码和注释。

  1 //////////////////////////////////////////////////////////////////////////
  2 //        POJ1025 Department
  3 //        Memory: 312K        Time: 94MS
  4 //        Language: C++        Result: Accepted
  5 //////////////////////////////////////////////////////////////////////////
  6 
  7 #include <iostream>
  8 #include <string>
  9 #include <cmath>
 10 #include<iomanip>
 11 
 12 using namespace std;
 13 
 14 enum Event {
 15     et_entry, et_wait_elevator, et_wait_room, et_room2room, et_elevator2room,    
 16     et_room2elevator, et_in_room, et_in_elevator, et_exit
 17 };
 18 const size_t event_time[] = {30, 5, 0, 10, 10, 10, 0, 30, 30};
 19 
 20 class Room {
 21 public:
 22     bool o;
 23     int free_time;
 24     bool waiting_queue[26];
 25     int waiting_cnt;
 26 
 27     bool waiting_q_empty() {
 28         return waiting_cnt == 0 ? true :false;
 29     }
 30     void push(int agent_id) {
 31         waiting_queue[agent_id] = true;
 32         ++waiting_cnt;
 33     }
 34     int pop() {
 35         for (int i = 0; i < 26; ++i) {
 36             if (waiting_queue[i] == true) {
 37                 waiting_queue[i] = false;
 38                 --waiting_cnt;
 39                 return i;
 40             }
 41         }
 42     }
 43 };
 44 Room room[11][11];
 45 int current_time;
 46 class Plan {
 47 public:
 48     pair<int, int> p;
 49     Plan * next;
 50 };
 51 class Schedule {
 52 public:
 53     Event e;
 54     int start_time;
 55     int end_time;
 56     int from;
 57     int to;
 58     Schedule * next;
 59 
 60     Schedule () {
 61         from = 0;
 62         to = 0;
 63         next = NULL;
 64     }
 65 };
 66 class Agent {
 67 public:
 68     bool e;                //是否存在该Agent
 69     int id;
 70     int entry_time;
 71     int exit_time;
 72     Plan * plan;
 73     Schedule * schedule;
 74 
 75     void push_plan(pair<int, int> p) {
 76         Plan * pl = new Plan;
 77         Plan * pt;
 78         pl->p = p;
 79         pl->next = NULL;
 80         if (plan == NULL) {
 81             plan = pl;
 82             return;
 83         }
 84         for (pt = plan; pt->next != NULL; pt = pt->next) ;
 85         pt->next = pl;
 86     }
 87 
 88     pair<int, int> popr_plan() {
 89         return plan->p;
 90     }
 91 
 92     pair<int, int> pop_plan() {
 93         pair<int, int> pp = plan->p;
 94         plan = plan->next;
 95         return pp;
 96     }
 97 
 98     void push_schedule(Schedule * s) {
 99         Schedule * ps;
100         if (schedule == NULL) {
101             schedule = s;
102             s->next = NULL;
103             return;
104         }
105         for (ps = schedule; ps->next != NULL; ps = ps->next) ;
106         ps->next = s;
107         s->next = NULL;
108     }
109     Schedule * popr_schedule() {
110         Schedule * ps;
111         for (ps = schedule; ps->next != NULL; ps = ps->next) ;
112         return ps;
113     }
114 };
115 Agent agent[26];
116 
117 void enqueue(int agent_id, int room_id) {
118     Schedule * s = new Schedule;
119     int floor = room_id / 100;
120     int id = room_id % 100;
121     room[floor][id].push(agent_id);
122     if (id == 0) {
123         s->e = et_wait_elevator;
124     } else {
125         s->e = et_wait_room;
126     }
127     s->start_time = current_time;
128     s->end_time = room[floor][id].free_time > current_time ? room[floor][id].free_time : current_time;
129     s->from = room_id;
130     if (agent[agent_id].plan == NULL) {
131         s->to = -1;
132     } else {
133         s->to = agent[agent_id].popr_plan().first;
134     }
135     agent[agent_id].push_schedule(s);
136 }
137 void process(int agent_id) {
138     Schedule * s = agent[agent_id].popr_schedule();
139     int from = s->from;
140     int to = s->to;
141     int floor = to / 100;
142     int id = to % 100;
143     switch (s->e) {
144             case et_entry:
145                 //第一个房间在1楼,则已到达该房间
146                 if (floor == 1) {
147                     //插入房间等待队列
148                     enqueue(agent_id, to);
149                 } else {
150                     //第一个房间在楼上,则已到达电梯,插入该电梯等候队列
151                     enqueue(agent_id, 100);
152                 }
153                 break;
154             case et_wait_elevator:
155                 //留在电梯等候队列
156                 break;
157             case et_wait_room:
158                 //留在房间等候队列
159                 break;
160             case et_room2room:
161                 //到达房间,插入房间等候队列
162                 enqueue(agent_id, to);
163                 break;
164             case et_elevator2room:
165                 //到达房间,插入房间等候队列
166                 enqueue(agent_id, to);
167                 break;
168             case et_room2elevator:
169                 //到达电梯,插入电梯等候队列
170                 enqueue(agent_id, from / 100 * 100);
171                 break;
172             case et_in_room:
173                 //出房间,去电梯或去下一房间或exit
174                 room[from / 100][from % 100].o = false;
175                 if (to == -1) {
176                     //即将exit
177                     if (from / 100 == 1) {
178                         Schedule * s = new Schedule;
179                         s->e = et_exit;
180                         s->start_time = current_time;
181                         s->end_time = current_time + event_time[et_exit];
182                         s->from = -1;
183                         s->to = -1;
184                         agent[agent_id].push_schedule(s);
185                     } else {
186                         //即将下电梯然后exit
187                         Schedule * s = new Schedule;
188                         s->e = et_room2elevator;
189                         s->start_time = current_time;
190                         s->end_time = current_time + event_time[et_room2elevator];
191                         s->from = from; 
192                         s->to = -1;
193                         agent[agent_id].push_schedule(s);
194                     }
195                 } else if (floor == from / 100) {
196                     //下一房间在同一楼,room2room
197                     Schedule * s = new Schedule;
198                     s->e = et_room2room;
199                     s->start_time = current_time;
200                     s->end_time = current_time + event_time[et_room2room];
201                     s->from = from;
202                     s->to = to;
203                     agent[agent_id].push_schedule(s);
204                 } else {
205                     //下一房间在不同楼,room2elevator
206                     Schedule * s = new Schedule;
207                     s->e = et_room2elevator;
208                     s->start_time = current_time;
209                     s->end_time = current_time + event_time[et_room2elevator];
210                     s->from = from;
211                     s->to = to;
212                     agent[agent_id].push_schedule(s);
213                 }
214                 break;
215             case et_in_elevator:
216                 //出电梯,去下一房间或exit
217                 if (to == -1) {
218                     //exit
219                     Schedule * s = new Schedule;
220                     s->e = et_exit;
221                     s->start_time = current_time;
222                     s->end_time = current_time + event_time[et_exit];
223                     agent[agent_id].push_schedule(s);
224                 } else {
225                     //去房间
226                     Schedule * s = new Schedule;
227                     s->e = et_elevator2room;
228                     s->start_time = current_time;
229                     s->end_time = current_time + event_time[et_room2room];
230                     s->from = from;
231                     s->to = to;
232                     agent[agent_id].push_schedule(s);
233                 }
234                 break;
235             case et_exit: 
236                 //该agent所有plan和schedule已完成
237                 agent[agent_id].exit_time = s->end_time;
238                 break;
239     }
240 }
241 
242 int str2int(string time) {
243     return ((time[0] - '0') * 10 + (time[1] - '0')) * 3600 + 
244         ((time[3] - '0') * 10 + (time[4] - '0')) * 60 + 
245         (time[6] - '0') * 10 + (time[7] - '0');
246 }
247 
248 string int2str(int time) {
249     string str;
250     str += time / 3600 / 10 + '0';
251     str += time / 3600 % 10 + '0';
252     str += ":";
253     time = time - time / 3600 * 3600;
254     str += time / 60 / 10 + '0';
255     str += time / 60 % 10 + '0';
256     str += ":";
257     time = time - time / 60 * 60;
258     str += time / 10 + '0';
259     str += time % 10 + '0';
260     return str;
261 }
262 void input() {
263     while (true) {
264         char prio;
265         cin >> prio;
266         if (prio == '.') {
267             break;
268         }
269         int agent_id = prio - 'A';
270         agent[agent_id].e = true;
271         string entry;
272         cin >> entry;
273         int entry_time = str2int(entry);
274         agent[agent_id].entry_time = entry_time;
275         //读入计划
276         while (true) {
277             int room_id;
278             cin >> room_id;
279             if (room_id == 0) {
280                 break;
281             }
282             int time;
283             cin >> time;
284             agent[agent_id].push_plan(make_pair(room_id, time));
285         }
286         //将entry event写入schedule
287         Schedule * schedule = new Schedule;
288         schedule->e = et_entry;
289         schedule->start_time = entry_time;
290         schedule->end_time = entry_time + event_time[et_entry];
291         schedule->from = 0;
292         schedule->to = agent[agent_id].popr_plan().first;
293         schedule->next = NULL;
294         agent[agent_id].push_schedule(schedule);
295     }
296 }
297 void initialize() {
298     for (int i = 0; i < 26; ++i) {
299         agent[i].e = false;
300         agent[i].id = i;
301         agent[i].entry_time = -1;
302         agent[i].exit_time = 86401;
303         agent[i].plan = NULL;
304         agent[i].schedule = NULL;
305     }
306     for (int i = 0; i < 11; ++i) {
307         for (int j = 0; j < 11; ++j) {
308             room[i][j].waiting_cnt = 0;
309             for (int k = 0; k < 26; ++k) {
310                 room[i][j].o = false;
311                 room[i][j].free_time = 0;
312                 room[i][j].waiting_queue[k] = false;
313             }
314         }
315     }
316 } 
317 
318 void print_entry(int start, int end) {
319     cout << int2str(start) << " " << int2str(end) << " Entry" << endl;
320 }
321 void print_exit(int start, int end) {
322     cout << int2str(start) << " " << int2str(end) << " Exit" << endl;
323 }
324 void print_in_room(int start, int end, int room) {
325     cout << int2str(start) << " " << int2str(end) << " Stay in room " 
326         <<  setfill('0') << setw(4) << room << endl;
327 }
328 void print_in_elevator(int start, int end) {
329     cout << int2str(start) << " " << int2str(end) << " Stay in elevator" << endl; 
330 }
331 void print_room2room(int start, int end, int from, int to) {
332     cout << int2str(start) << " " << int2str(end) << " Transfer from room " 
333         << setfill('0') << setw(4) << from << " to room " << setfill('0') << setw(4) << to << endl;
334 }
335 void print_elevator2room(int start, int end, int room) {
336     cout << int2str(start) << " "  << int2str(end) << " Transfer from elevator to room " 
337         << setfill('0') << setw(4) << room << endl;
338 }
339 void print_room2elevator(int start, int end, int room) {
340     cout << int2str(start) << " " << int2str(end) << " Transfer from room " 
341         << setfill('0') << setw(4) << room << " to elevator" << endl;
342 }
343 void print_wait_room(int start, int end, int room) {
344     if (start == end) return;
345     cout << int2str(start) << " " << int2str(end) << " Waiting in front of room " 
346         << setfill('0') << setw(4) << room << endl;
347 }
348 void print_wait_elevator(int start, int end) {
349     if (start == end) return;
350     cout << int2str(start) << " " << int2str(end) << " Waiting in elevator queue" << endl;
351 }
352 void output() {
353     for (int i = 0; i < 26; ++i) {
354         if (agent[i].e == false) {
355             continue;
356         }
357         cout << char('A' + i) << endl;
358         Schedule * schedule = agent[i].schedule;
359         while (schedule != NULL) {
360             switch (schedule->e) {
361                 case et_entry: print_entry(schedule->start_time, schedule->end_time); break;
362                 case et_wait_elevator: print_wait_elevator(schedule->start_time, schedule->end_time); break;
363                 case et_wait_room: print_wait_room(schedule->start_time, schedule->end_time, schedule->from); break;
364                 case et_room2room: print_room2room(schedule->start_time, schedule->end_time, schedule->from, schedule->to); break;
365                 case et_elevator2room: print_elevator2room(schedule->start_time, schedule->end_time, schedule->to); break;
366                 case et_room2elevator: print_room2elevator(schedule->start_time, schedule->end_time, schedule->from);break; 
367                 case et_in_room: print_in_room(schedule->start_time, schedule->end_time, schedule->from); break; 
368                 case et_in_elevator: print_in_elevator(schedule->start_time, schedule->end_time); break;
369                 case et_exit: print_exit(schedule->start_time, schedule->end_time); break;
370             }
371             schedule = schedule->next;
372         }
373         cout << endl;
374     }
375 }
376 int main() {
377     initialize();
378     input();
379     for (current_time = 0; current_time < 24 * 3600; ++current_time) {
380         //处理每个客户的schedule
381         for (int agent_id = 0; agent_id < 26; ++agent_id) {
382             //没有该客户
383             if (agent[agent_id].e == false) continue;
384             //该客户该时刻还未到达
385             if (current_time < agent[agent_id].entry_time + event_time[et_entry]) continue;
386             //该客户该时刻已经离开
387             if (current_time > agent[agent_id].exit_time) continue;
388             Schedule * s = agent[agent_id].popr_schedule();
389             //该顾客上一schedule还未完成
390             if (current_time < s->end_time) continue;
391             //该顾客上一schedule恰好完成,准备下一schedule
392             if (current_time == s->end_time) {
393                 process(agent_id);
394             }
395         }
396         //处理每个房间和电梯的等待队列
397         for (int floor = 1; floor < 11; ++floor) {
398             for (int id = 0; id < 11; ++id) {
399                 //电梯5秒一趟
400                 if (id == 0) {
401                     if (current_time % 5 != 0) {
402                         //所有队列继续等待
403                         for (int k = 0; k < 26; ++k) {
404                             if (room[floor][id].waiting_queue[k] == true) {
405                                 agent[k].popr_schedule()->end_time = current_time + 5 - current_time % 5 ;
406                             }
407                         }
408                     } else {
409                         //电梯来了!
410                         room[floor][id].o = false;
411                         if (!room[floor][id].waiting_q_empty()) {
412                             //队列中的第一个进入电梯
413                             int agent_id = room[floor][id].pop();
414                             room[floor][id].o = true;
415                             room[floor][id].free_time = current_time + 5;
416                             Schedule * s = new Schedule;
417                             s->e = et_in_elevator;
418                             s->start_time= current_time;
419                             int des = agent[agent_id].popr_schedule()->to;
420                             if (des == -1) {
421                                 s->end_time = current_time + (floor - 1) * event_time[et_in_elevator];
422                             } else {
423                                 s->end_time = current_time + abs(agent[agent_id].popr_schedule()->to / 100 - floor) * event_time[et_in_elevator];
424                             }
425                             s->from = floor * 100 + id;
426                             s->to = agent[agent_id].popr_schedule()->to;
427                             agent[agent_id].push_schedule(s);
428                             //其余继续等候
429                             for (int i = 0; i < 26; ++i) {
430                                 if (room[floor][id].waiting_queue[i] == true) {
431                                     agent[i].popr_schedule()->end_time = current_time + 5;
432                                 }
433                             }
434                         }
435                     }
436                 } else {
437                     //是房间
438                     if (room[floor][id].o == true) continue; //该房间当前有人
439                     if (!room[floor][id].waiting_q_empty()) {
440                         //队列第一人进入房间
441                         int first_agent = room[floor][id].pop();
442                         int duration = agent[first_agent].pop_plan().second;
443                         Schedule * s = new Schedule;
444                         s->e = et_in_room;
445                         s->start_time = current_time;
446                         s->end_time = current_time + duration;
447                         s->from = floor * 100 + id;
448                         if (agent[first_agent].plan != NULL) {
449                             s->to = agent[first_agent].popr_plan().first;
450                         } else {
451                             s->to = -1;
452                         }
453                         agent[first_agent].push_schedule(s);
454                         room[floor][id].o = true;
455                         room[floor][id].free_time = current_time + duration;
456                         //其余继续等候
457                         for (int i = 0; i < 26; ++i) {
458                             if (room[floor][id].waiting_queue[i] == true) {
459                                 agent[i].popr_schedule()->end_time = room[floor][id].free_time;
460                             }
461                         }
462                     }
463                 }
464             }
465         }
466     }
467     output();
468     system("pause");
469     return 0;
470 }
View Code
posted @ 2013-07-31 21:31  小菜刷题史  阅读(468)  评论(0编辑  收藏  举报