浙大 PAT 甲级 1014 Waiting in Line

一道简单的模拟题。黄线以前是N条队伍,每条队伍容量为M。黄线以后可以看作只有一条队伍,现将黄线前的N条队伍排满(如果可以排满的话),每当某队有人离开,黄线后的人补上去,如果同时有多人离开,按照队伍编号从小到大补上去。

我定义了一个结构体Customer代表每位排队人员,存放编号和结束时间。我用的数据结构是vector<queue<Customer>>,用来模拟N个队列。先开始队列都为空,二重循环依次排满整个队列,如果能排完最好,不能排完继续下一个一重循环,将模拟剩余人员的补位。思路很寻常,依照题目意思直接写代码即可。

但是要注意以下一个问题:

Note that since the bank is closed everyday after 17:00, for those customers who cannot be served before 17:00, you must output Sorry instead.

是指17:00之前没有开始办理业务的,则输出Sorry,这个17:00并不是指结束时间。而且是17:00之前,不包含17:00.

这个处理直接写一个条件判断即可,不影响整体的排队,也不用为此而考虑特殊情况或者更改排队机制。

我之前是定义了一个res[1001]数组用于存放每个人的结束时间,下标即该人员编号。用当前排队人员的结束时间减去他办理业务需要的时间就能得到他的开始办理时间了。如果大于等于17:00,则将res[i]设为-1,如果小于17:00,则将res[i]赋值为结束时间。然后照常进行出队入队操作。

具体代码如下。刚开始练习写代码,所以我的代码可能不简洁,有些地方思路复杂了或者不够普遍性,见谅。

#include<stdio.h>
#include<queue>
#include<vector>
using namespace std;

struct Customer
{
    int index;
    int dtime;
};
vector<queue<Customer>> lines;
int res[1001];

int main()
{
    int N, M, K, Q;
    scanf("%d%d%d%d", &N, &M, &K, &Q);
    for (int i = 0; i < N; i++)
    {
        queue<Customer> line;
        lines.push_back(line);
    }
    for (int i = 0; i <= N; i++)
    {
        res[i] = -1;
    }
    for (int i = 0; i < M; i++)
    {
        int loop = true;
        for (int j = 1; j <= N; j++)
        {
            int time = 0;
            scanf("%d", &time);
            Customer c;
            c.index = i*N + j;
            if (lines[j - 1].empty() == false)
            {
                c.dtime = lines[j - 1].back().dtime + time;
            }
            else
            {
                c.dtime = time;
            }
            lines[j - 1].push(c);
            if (c.dtime - time >= 540)
            {
                res[c.index] = -1;
            }
            else
            {
                res[c.index] = c.dtime;
            }
            if (c.index == K)
            {
                loop = false;
                break;
            }
        }
        if (loop == false)
        {
            break;
        }
    }
    for (int i = 0; i < K - M*N; i++)
    {
        int bestline = 0;
        int besttime = 10000000;
        for (int j = 0; j < N; j++)
        {
            if (lines[j].front().dtime < besttime)
            {
                besttime = lines[j].front().dtime;
                bestline = j;
            }
        }
        int time = 0;
        scanf("%d", &time);
        Customer c;
        c.index = M*N + i + 1;
        c.dtime = lines[bestline].back().dtime + time;
        lines[bestline].pop();
        lines[bestline].push(c);
        if (c.dtime - time >= 540)
        {
            res[c.index] = -1;
        }
        else
        {
            res[c.index] = c.dtime;
        }
    }
    for (int i = 0; i < Q; i++)
    {
        int p = 0;
        scanf("%d", &p);
        if (res[p] == -1)
        {
            printf("Sorry\n");
            continue;
        }
        printf("%02d:%02d\n", 8 + res[p] / 60, res[p] % 60);
    }
    return 0;
}

个人感觉,刷这类题,细节真的要重要,尤其对英文不熟练的话,很多地方题目也不会告诉的那么直白,甚至还需要动用生活经验。总之,代码容易,但健壮性好的代码很难,有时候为通过最后一两个用例要花更多时间。

希望考PAT能够为去浙大加点分哈哈哈。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值