1. 程式人生 > >[PAT甲級]1014. Waiting in Line (30)(銀行排隊辦理業務結束時間 佇列的應用)

[PAT甲級]1014. Waiting in Line (30)(銀行排隊辦理業務結束時間 佇列的應用)

1014. Waiting in Line (30)

原題連結
相似題目 1017. Queueing at Bank (25)
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:

  • 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.
  • 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.

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 custmers 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, customer1 is served at window1 while customer2 is served at window2. Customer3 will wait in front of window1 and customer4 will wait in front of window2. Customer5 will wait behind the yellow line.

At 08:01, customer1 is done and customer5 enters the line in front of window1 since that line seems shorter now. Customer2 will leave at 08:02, customer4 at 08:06, customer3 at 08:07, and finally customer5 at 08:10.

Input

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.

Output

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.

Sample Input

2 2 7 5
1 2 6 4 3 534 2
3 4 5 6 7

Sample Output

08:07
08:06
08:10
17:00
Sorry

題目大意:

  • 銀行排隊辦理業務,有n個視窗,每個視窗前有黃線,黃線內最多排m個人,剩下的人在黃線外等候
  • 給出k個人,並給出他們辦理業務所需要的時間time,查詢p個人的辦理業務結束時間,如果開始辦理業務時超過了17:00,輸出sorry
  • 08:00開始辦理業務,17:00結束辦理業務,如果業務已經開始辦理,就繼續辦理直到辦理業務結束窗口才關門。
  • 如果某個視窗有人辦理業務結束,黃線外的人去那個視窗的隊尾等候,如果兩個視窗同時有人辦理業務結束,就選擇視窗號較小的

思路:

  • 這道題考察佇列的應用
  • 設定結構體,包含隊首的人出隊(結束)時間poptime,隊尾的人結束時間endtime,佇列q包含隊伍內每個人辦理業務所需要的時間
  • 設定poptime,方便計算黃線外的何時能入隊
  • 設定endtime,判斷後面入隊的人是否需要輸出sorry
  • 陣列result儲存每個人結束時間,用分鐘計算,最後輸出轉化為XX:XX比較方便
  • 陣列sorry記錄是否需要輸出sorry
  • 先處理能夠排進黃線內的人,再入隊出隊處理在黃線外等候的人

程式碼:

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
struct node{
    int poptime, endtime;//隊首的人出隊(結束)時間  隊尾的人結束時間
    queue<int> q;
};
int main()
{
    //n個視窗(n<=20) m為黃線內最大容量(m<=10) k個顧客(k<=1000) q為要查詢的顧客人數(q<=1000)
    int n, m, k, p, index=1;
    scanf("%d%d%d%d", &n, &m, &k, &p);
    vector<int> time(k+1), result(k+1);//顧客辦理業務所需時間  顧客辦理業務結束時間
    for(int i=1; i<=k; i++)
        scanf("%d", &time[i]);
    vector<node> window(n+1);//n個視窗n個隊
    vector<bool> sorry(k+1, false);
    //處理開始就在黃線內顧客 前面m*n
    for(int i=1; i<=m; i++){
        for(int j=1; j<=n; j++){
            if(index <= k){
                window[j].q.push(time[index]);
                if(window[j].endtime >= 540)//隊尾的人結束時間超過下午五點
                    sorry[index] = true;
                window[j].endtime += time[index];
                result[index] = window[j].endtime;
                index++;
            }
        }
    }
    //開始無法排進黃線內  m*n以後的人
    while(index <= k){
        int minPoptime=window[1].poptime, minWindow=1;
        for(int i=2; i<=n; i++){//尋找最先有人出來的視窗
            if(window[i].poptime < minPoptime){
                minPoptime = window[i].poptime;
                minWindow = i;
            }
        }
        window[minWindow].q.pop();//出隊一個
        window[minWindow].q.push(time[index]);//入隊
        window[minWindow].poptime += window[minWindow].q.front();//更新隊首結束時間
        if(window[minWindow].endtime >= 540)
            sorry[index] = true;
        window[minWindow].endtime += time[index];//更新隊尾結束時間
        result[index] = window[minWindow].endtime;//記錄該顧客結束時間
        index++;
    }
    for(int i=1; i<=p; i++){
        int check;
        scanf("%d", &check);
        int temp = result[check];
        if(sorry[check] == true)
            printf("Sorry\n");
        else
            printf("%02d:%02d\n", (temp+480)/60, (temp+480)%60);//480 早上八點
    }
    return 0;
}