zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    EasyUI左边树菜单和datagrid分页
    Linux上安装Redis教程
    TreeMap和TreeSet的区别与联系
    将Map<String, List<Map<String,Object>>>进行排序
    Linux系统安装JDK和Tomcat
    点击添加按钮,使用ajax动态添加一行和移除一行,并且序号重新排序和数据不重复操作判断
    23种设计模式汇总整理
    SSH架构BaseDao实现
    双击Table表格td变成text修改内容
    用户找回密码功能JS验证邮箱通过点击下一步隐藏邮箱输入框并修改下一步按钮的ID
  • 原文地址:https://www.cnblogs.com/dengeven/p/3228895.html
Copyright © 2011-2022 走看看