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 }