PAT(甲)1014 Waiting in Line (30)(详解)

1014 Waiting in Line (30)

题目描述:

Suppose a bank has N windows open for service. There is a yellow line in front of the windows which devides the waiting area into two parts. The rules for the customers to wait in line are:
    1. The space inside the yellow line in front of each window is enough
to contain a line with M customers. Hence when all the N lines are
full, all the customers after (and including) the (NM+1)st one will
have to wait in a line behind the yellow line.
   2. Each customer will choose the shortest line to wait in when crossing
the yellow line. If there are two or more lines with the same
length, the customer will always choose the window with the smallest
number. Customer[i] will take T[i] minutes to have his/her
transaction processed. The first N customers are assumed to be
served at 8:00am.
   3. Now given the processing time of each customer, you are supposed to tell the exact time at which a customer has his/her business done.

For example, suppose that a bank has 2 windows and each window may have 2 customers
waiting inside the yellow line. There are 5 customers waiting with transactions taking 1, 2, 6, 4 and 3 minutes, respectively. At 08:00 in the morning, customer~1~ is served at window~1~ while customer~2~ is served at window~2~. Customer~3~ will wait in front of window~1~ and customer~4~ will wait in front of window~2~. Customer~5~ will wait behind the yellow line.

At 08:01, customer~1~ is done and customer~5~ enters the line in front of window~1~ since that line seems shorter now. Customer~2~ will leave at 08:02, customer~4~ at 08:06, customer~3~ at 08:07, and finally customer~5~ at 08:10.


  • 输入格式
    Each input file contains one test case. Each case starts with a line containing 4 positive integers: N (<=20, number of windows), M (<=10, the maximum capacity of each line inside the yellow line), K (<=1000, number of customers), and Q (<=1000, number of customer queries).The next line contains K positive integers, which are the processing time of the K customers.
    The last line contains Q positive integers, which represent the customers who are asking about the time they can have their transactions done. The customers are numbered from 1 to K.

  • 输出格式
    For each of the Q customers, print in one line the time at which his/her transaction is finished, in the format HH:MM where HH is in [08, 17] and MM is in [00, 59]. 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.


解题方法:
这里我建立了一个结构体,里面的成员是窗口队列、窗口第一个人结束时间、窗口最后一个人结束时间。首先将前M*N个顾客放入队列中(当然可能不足M*N个人),与此同时记录每一个窗口的队头顾客的出队时间。然后如果超过M*N个顾客的话,后面的顾客可以从每个窗口中找到顾客最早出队的时间,从中选择最小的窗口,进行排队。这样就能得到结果(代码附详细注解)


易错点:
这里要注意在5点之前(不包含5点)所办理的业务照常完成,但是超过5点的就不能完成了


程序:

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

struct Window
{
    queue <int> Queue;
    int pop, end;   /* 保存每个队列的队头元素出队时间 */
};

int main(int argc, char const *argv[])
{
    int N, M, K, Q, x, idx = 1, temp = 1;
    scanf("%d %d %d %d", &N, &M, &K, &Q);
    Window W[K+5];
    int overTime[K+5], NeedTime[K+5];
    for (int i = 1; i <= M; i++)    /* 将开始的M*N的人进行分配 */
        for (int j = 1; j <= N; j++)
            if (idx <= K)   /* 防止出现人数还不足M*N的情况 */
            {
                scanf("%d", &x);
                NeedTime[idx] = x;  /* 保存每个人所需要的时间 */
                W[j].Queue.push(x);
                if (i == 1) /* 每个窗口排队的第一个人 */
                    W[j].pop = overTime[idx] = x;
                else
                    overTime[idx] = overTime[idx - N] + x;
                idx++;
            }
    for (int i = idx-N; i <= idx-1; i++)
        W[temp++].end = overTime[i];    /* 计算每个窗口刚好排满时的最后一个人离开的时间 */
    while (idx <= K) /* 如果还有人在排队(超过MN) */
    {
        scanf("%d", &x);
        NeedTime[idx] = x;
        int earlypop = W[1].pop, tempIdx = 1;
        for (int i = 2; i <= N; i++)
            if (W[i].pop < earlypop)
            {   /* 找出最早出队的人 */
                tempIdx = i;    /* 保存窗口下标 */
                earlypop = W[i].pop;
            }
        W[tempIdx].Queue.pop(); /* 人出队 */
        W[tempIdx].Queue.push(x);   /* 新客户入队 */
        W[tempIdx].pop += W[tempIdx].Queue.front();  /* 更新该窗口的下一个出队时间 */
        overTime[idx] = W[tempIdx].end + x; /* 计算该人的结束时间 */
        W[tempIdx].end = overTime[idx]; /* 更新该窗口最后一个人的结束时间 */
        idx++;
    }
    for (int i = 1; i <= Q; i++)
    {
        scanf("%d", &x);
        if ((overTime[x] - NeedTime[x]) >= 540)
            printf("Sorry\n");
        else
            printf("%02d:%02d\n", overTime[x] / 60 + 8, overTime[x] % 60); 
    }
    return 0;
}

如果对您有帮助,帮忙点个小拇指呗~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章