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

题目

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 customer

typedef 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值