• POJ #1025 Department


    模拟题。

    这题第一个障碍是现在少见的循环电梯 ('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;
    }
  • 相关阅读:
    动手动脑
    原码反码补码
    考试感想
    第八周
    第七周
    第六周
    第五周
    第四周
    Hamburger Magi(hdu 3182)
    Doing Homework(hdu)1074
  • 原文地址:https://www.cnblogs.com/Patt/p/4116246.html
Copyright © 2020-2023  润新知