PTA 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:

  • 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.
  • The first N customers are assumed to be served at 8:00am.

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, customer1 is served at window1 while custome​2​​ is served at window2. Customer
​3 will wait in front of window​1​​ and customer​4​​ will wait in front of window2. Customer​5​​ will wait behind the yellow line.

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

Input Specification:
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 Specification:
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位用戶需要服務,給出了每位用戶服務需要占用的的minute數。
  • 銀行在8點開始服務,如果有窗口還沒排滿就在窗口前排隊,否則就在黃線外等候。如果有某一隊列有一個用戶走了服務完畢了,黃線外的人就進來一個。如果同時有多個窗口走了一個人,就選窗口數最小的那個窗口前去排隊。
  • 要求輸入q個人,以HH:mm的格式輸出他們的服務結束時間。銀行在17:00點停止服務,如果一個客戶在17:00以及以后還沒有開始服務(此處不是結束服務是開始17:00)就輸出Sorry。

易錯點分析

這個題最易錯的地方是如何判斷一個客戶無法完成服務,

是看他的結束時間是否超過17:00嗎??不不不不不,只要他在17:00前開始被服務,銀行就必須給他服務完才結束下班。所以我們要看他的開始服務時間是不是超過17:00,而不是結束時間!!!

解題思路

  • 既然是排隊,那么當然要用隊列了,每個窗口前都有一個隊,假如有n個窗口,那就建n個隊列唄,但是因為編號都是從1開始,所以直接建n+1個隊列好了
  • 使用結構體來保存顧客的信息,包括開始服務時間服務花費時間結束服務時間,這樣我們最后只需要看他的開始服務時間是否超過17:00就可以了。
  • 字符串形式時間不好判斷,題目中給出的是以分鍾為單位的,那么我們直接用int保存就可以了,8:00就相當於8*60,17:00就相當於17*60,最后輸出HH:mm很好辦printf("%02d:%02d\n", customer[id].end_time / 60, customer[id].end_time % 60);
  • 首先銀行開始服務,每個窗口前可以排m個人,那么前n*m個人可以直接排到黃線前面,所以這部分人要單獨處理,后面的人才需要等前面有人走了再去排隊。
  • 對於黃線后面的人,逐個分析,首先判斷所有窗口前的隊列中的隊首元素,看那個人的服務結束時間,找到最早的那個,讓那個人出隊,然后他排到這條隊伍后面,這就相當於實現了題目中他總是選擇排到最短的隊伍后面

滿分代碼

個人覺得我代碼注釋夠清楚了,應該都能看懂的吧,哈哈。

#include <iostream>
#include <queue>
using namespace std;

struct Customer {
    int cost_time, start_time, end_time;
} customer[1001];

int main() {

    // n個窗口,每個窗口到黃線,最多排m個人,k個客戶,有q個客戶想知道他啥時候被服務結束
    int n, m, k, q;
    cin >> n >> m >> k >> q;
    // 銀行開始服務時間,結束服務時間
    int open_time = 8 * 60, close_time = 17 * 60;
    // n個窗口,從1開始
    queue<Customer> windows[n + 1];

    // 讀入k個人花費的時間
    for (int i = 1; i <= k; ++i)
        cin >> customer[i].cost_time;
    // 排隊
    for (int i = 1; i <= k; ++i) {
        // 黃線內能排 n * m個人
        if (i <= n * m) {
            // 按順序挨個窗口,顧客id和窗口id都從1開始
            int window = (i - 1) % n + 1;
            // 前n個人,一人一個窗口
            if (i <= n) {
                // 開始時間是銀行開始服務時間
                customer[i].start_time = open_time;
                // 他的結束時間是他的開始加+他的服務時間
                customer[i].end_time = open_time + customer[i].cost_time;
            } else {
                Customer last_customer = windows[window].back();
                // 他的開始時間是上一個人的結束時間
                customer[i].start_time = last_customer.end_time;
                // 他的結束時間是他的開始加+他的服務時間
                customer[i].end_time = customer[i].start_time + customer[i].cost_time;
            }
            // 排到對應窗口
            windows[window].push(customer[i]);
        // 黃線外的人
        } else {
            // 看哪一個窗口先離開一個人,就是看每個窗口前那個隊伍中第一個人的離開時間
            int window = 1;
            for (int j = 2; j <= n; ++j) {
                // 除非第一個人離開的更早,才選擇這個窗口
                if (windows[j].front().end_time <
                    windows[window].front().end_time) {
                    window = j;
                }
            }
            // 這個窗口第一個人出隊
            windows[window].pop();
            // 排到這個窗口
            Customer last_customer = windows[window].back();
            // 他的開始時間是上一個人的結束時間
            customer[i].start_time = last_customer.end_time;
            // 他的結束時間是他的開始加+他的服務時間
            customer[i].end_time = customer[i].start_time + customer[i].cost_time;
            //入隊
            windows[window].push(customer[i]);
        }
    }
    // q個人想要查詢自己什么時間能結束
    int id;
    while (q-- > 0) {
        cin >> id;
        // 開始服務時間超過了銀行關門時間,無法服務
        if (customer[id].start_time >= close_time)
            cout << "Sorry" << endl;
        else
            printf("%02d:%02d\n", customer[id].end_time / 60,
                   customer[id].end_time % 60);
    }

    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM