PAT 1014 Waiting in Line(模拟+队列操作)

来源:互联网 发布:天龙八部淘宝抢号行吗 编辑:程序博客网 时间:2024/06/05 17:35

题目

https://www.patest.cn/contests/pat-a-practise/1014

银行前台处理客户的过程如下,有n个窗口,每个窗口前的队伍可以排m个人,其余人在黄线外等待;每当有人处理完毕时,黄线外的人找最短的、序号最小队伍插入;求每个人的结束时间。

解题思路

本题是明显的队列的模拟题,遗憾的是改了好久代码只过了四组,最后一组依然是段错误,虽然还不知道什么原因:(,看了一下网上大神的代码,非常简练明了,五体投地。(参考:http://blog.csdn.net/acm_ted/article/details/20473255)

先把n*m个客户加入对应的n的窗口队列中,如果还有客户,枚举判断出n个窗口中最早处理完的队列,然后将用户加入此队列。
最后将时间和时限进行比较,输出。

和自己实现的相比,有两个最大的不同:

  • 为每个客户构造一个结构体,记录耗时,开始时间和结束时间
  • 利用了每位顾客插入队伍时,就决定了什么时候轮到他,什么时候离开,因此没必要完全模拟,处理直到所有队列都为空,不然会比较杂乱不够清晰

需要注意的是,如果一个顾客在17:00前(<=16:59)能轮到即可,不要求在17:00前处理完毕。

AC代码

参考别人博客修改后的代码

#include <iostream>#include <cstdio>#include <queue>using namespace std;const int INF = 0x3f3f3f3f;const int maxcnt = 1005;const int maxn = 25;typedef struct node{    int wasteTime; //每位顾客耗时    int sTime,eTime; //开始和结束时间}customer;typedef struct windows{    int eTime; //本窗口处理完的时间    queue<int> q;}window;///利用了每位顾客插入队伍时,就决定了什么时候轮到他,什么时候离开,没必要完全模拟直到队列都空了int main(){    customer cust[maxcnt];    window win[maxn];    int n,m,cnt,q;    int num, minTime, idx, pos;    cin >> n >> m >> cnt >> q;    for (int i = 1; i <= cnt; ++i)        cin >> cust[i].wasteTime;    num = 1;    int first = min(n*m, cnt);    for (int i = 0; num <= first; ++num, i=(i+1)%n) //插入第一批顾客    {        cust[num].sTime = win[i].eTime;        cust[num].eTime = cust[num].sTime + cust[num].wasteTime; //顾客的时间确定,用于输出他自己        win[i].eTime += cust[num].wasteTime; //窗口的结束时间确定,用于下一个客户的初始化        win[i].q.push(num);    }    for (; num <= cnt; ++num) //处理剩余的顾客    {        minTime = INF;        for (int i = 0; i<n; ++i) //找到队列中能最先完成的        {            idx = win[i].q.front();            if (cust[idx].eTime < minTime)            {                minTime = cust[idx].eTime;                pos = i;            }        }        //插入新顾客的时间确定化        cust[num].sTime = win[pos].eTime;        cust[num].eTime = cust[num].sTime + cust[num].wasteTime;        win[pos].eTime += cust[num].wasteTime;        win[pos].q.pop();        win[pos].q.push(num);    }//插入完毕    int hour, minute, query;    while(q--)    {        cin >> query;        if (cust[query].sTime >= 540)            cout << "Sorry" << endl;        else        {            hour = (cust[query].eTime + 8*60)/60;            minute = (cust[query].eTime + 8*60)%60;            if (hour >= 10)                printf("%d:",hour);            else                printf("0%d:",hour);            if (minute>= 10)                printf("%d\n",minute);            else                printf("0%d\n",minute);        }    }    return 0;}

自己复杂的代码,最后一个测试点段错误

#include <iostream>#include <queue>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int INF = 0x3f3f3f3f;const int maxcnt = 1005;const int maxn = 25;int n, m, cnt;int cost[maxcnt]; //time needed for each customertypedef struct node{    queue<int> q;    int spent;}LINE;LINE win[maxn];int myTurn[maxn];void init(){    memset(myTurn, 0, sizeof(myTurn));    for (int i = 0; i < n; ++i)        win[i].spent = 0;    int first = min(n*m, cnt);    for (int i = 1; i <= first; ++i)        (win[(i-1) % n].q).push(i);}void calc_time(){    int minn, smallest;    for (int out = n*m+1; out <= cnt; ++out) //处理还在黄线外的人    {        minn = 0, smallest = INF;        for (int i = 0; i < n; ++i) //选择一个最早能空出来的队列编号minn        {            //发现一个空的队列            if (win[i].q.empty())            {                minn = i;                break;            }            //更新smallest和minn            int predict = win[i].spent + cost[(win[i].q).front()]; //本队列腾出空位的时间            if (predict < smallest)            {                smallest = predict;                minn = i;            }        }        if (win[minn].q.empty() == false) //所选队列不空        {            int who_pop = (win[minn].q).front();            win[minn].q.pop();            myTurn[who_pop] = win[minn].spent; //who_pop的开始时间为之前队列的耗时            win[minn].spent = smallest;        }        win[minn].q.push(out);    }    //黄线外已经处理完    for (int i = 0; i<n; ++i)    {        while(win[i].q.empty() == false)        {            myTurn[win[i].q.front()] = win[i].spent;            win[i].spent += cost[win[i].q.front()];            win[i].q.pop();        }    }}int main(){    int q;    cin >> n >> m >> cnt >> q;    for (int i = 1; i <= cnt; ++i)        cin >> cost[i];    init();    calc_time();    int query, start, hour, minu;    for (int i = 0; i < q; ++i)    {        cin >> query;        start = myTurn[query];        if (start >= 540)            cout << "Sorry" << endl;        else        {            hour = 8, minu = start + cost[query];            hour += (minu/60);            minu %= 60;            if (hour < 10) printf("0%d:", hour);            else printf("%d:",hour);            if (minu < 10) printf("0%d", minu);            else printf("%d",minu);            cout << endl;        }    }    return 0;}