PTA 甲級 1017 Queueing at Bank (25 分)【模擬】【排隊論】

題目

n個客戶,k個窗口。已知每個客戶的到達時間和需要的時長,如果有窗口就依次過去,如果沒有窗口就在黃線外等候(黃線外只有一個隊伍,先來先服務),求客戶的平均等待時長。銀行開放時間爲8點到17點,再8點之前不開門,8點之前來的人都要等待,在17點後來的人不被服務。

Suppose a bank has K windows open for service. There is a yellow line in front of the windows which devides the waiting area into two parts. All the customers have to wait in line behind the yellow line, until it is his/her turn to be served and there is a window available. It is assumed that no window can be occupied by a single customer for more than 1 hour.

Now given the arriving time T and the processing time P of each customer, you are supposed to tell the average waiting time of all the customers.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 numbers: N (≤10​4​​) - the total number of customers, and K (≤100) - the number of windows. Then N lines follow, each contains 2 times: HH:MM:SS - the arriving time, and P - the processing time in minutes of a customer. Here HH is in the range [00, 23], MM and SS are both in [00, 59]. It is assumed that no two customers arrives at the same time.

Notice that the bank opens from 08:00 to 17:00. Anyone arrives early will have to wait in line till 08:00, and anyone comes too late (at or after 17:00:01) will not be served nor counted into the average.

Output Specification:

For each test case, print in one line the average waiting time of all the customers, in minutes and accurate up to 1 decimal place.

Sample Input:

7 3
07:55:00 16
17:00:01 2
07:59:59 15
08:01:00 60
08:00:00 30
08:00:02 2
08:03:00 10

Sample Output:

8.2

分析

跟這道題非常相似。PAT 甲級 1014

 我完全照搬了1014題的思路,但是其實已經沒有必要給每個窗口設置一個隊列存儲了。

根據我腦子裏還剩餘的排隊論的知識, 1017 相當於單隊列多服務檯,它的排隊等待時間應該是比較少的。???

1017相當於每個窗口只有一個人在被服務,1014相當於每個窗口排了很多人(不超過黃線)。

首先, 將顧客的到來時間按照時間順序進行排列。(時間最好按照秒來統一單位,方便計算)沒到8點就來的顧客,要記得加上他們等待開門的這段時間;超過17點的顧客就再見吧。

然後,對滿足要求的顧客進行遍歷。(我這裏依舊沿襲了1014的思維,先排上第一輪,在去排剩餘的;因爲這裏等待區只有1,其實可以直接進行遍歷 , 參考柳神的代碼)如果該窗口的上次操作完成的時間poptime大於該顧客的時間,那麼該顧客需要等待;否則,就不需要等待。

最後,說一下題目有個測試點蜜汁尷尬。原文It is assumed that no window can be occupied by a single customer for more than 1 hour.這句話的意思是沒有一個顧客會佔用一個窗口超過一小時。但是,如果你將顧客的操作時間>60的顧客刪掉,那麼你將會在測試點4 扣掉2分。

代碼

#include<iostream>
#include<algorithm>
#include<sstream>
#include<queue>
#include<cmath>
#include<string.h>
#include<map>
#include<stack>
using namespace std;
typedef long long ll;
int N , K;
int cnt = 0;
double waittime = 0;
struct Record
{
    double time ;
    double proc;
};
vector < Record > records;

struct Window
{
    queue< Record > q;
    double poptime;
};
Window windows[105];

bool cmp(Record a , Record b)
{
    if(a.time == b.time)
        return a.proc < b.proc;
    else return a.time < b.time;
}

void pt(int time)
{

        int hh = time / 3600;
        int mm = (time - hh * 3600 ) / 60;
        int ss = (time) % 60;
        cout << hh << " : " << mm << " : " << ss ;
}

int main()
{
   // freopen("a.txt" , "r" , stdin);

    cin >> N >> K;

    for(int i = 0 ; i < N; i++)
    {
        int hh , mm , ss , p;
        char c;
        cin >> hh >> c >> mm >> c >> ss >> p;
        int t = hh * 3600 + mm * 60 + ss;

        if(t < 8 * 3600)
        {
            waittime += 8 * 3600 - t;
            t = 8 * 3600;
        }
        if(t > 17 * 3600 )  continue;

        Record tmp = {t , p};
        records.push_back(tmp);
      //  cout << tmp.time << " " << tmp.proc << endl;
        cnt ++;
    }
  //  cout << waittime << endl;
    sort(records.begin() , records.end() , cmp);

    int idx = 0;
    if(cnt == 0)
    {
        cout << "0.0" ;
        return 0;
    }

    while(idx < cnt && idx < K)//絕對不需要等待
    {

        windows[idx].poptime = records[idx].time + records[idx].proc * 60;
        idx ++;
    }

    while(idx < cnt)
    {
        int mintime = windows[0].poptime;
        int minidx = 0;
        double curwait = 0;
        for(int i = 1; i < K ; i ++)
        {
            if(windows[i].poptime < mintime)
            {
                mintime = windows[i].poptime;
                minidx = i;
            }
        }

        if(windows[minidx].poptime <= records[idx].time)
        {
            curwait = 0;
            windows[minidx].poptime = records[idx].time + records[idx].proc * 60;
        }
        else
        {
            curwait =  (windows[minidx].poptime - records[idx].time);
            windows[minidx].poptime += records[idx].proc * 60;
        }

        waittime += curwait;
        idx ++;
    }
    double ans = waittime / 60.0 / cnt;
    printf("%0.1f" , ans);

}

 

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