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;
}

如果對您有幫助,幫忙點個小拇指唄~

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