PAT甲级1026. Table Tennis (30)

来源:互联网 发布:kt交易师软件下载 编辑:程序博客网 时间:2024/05/20 03:44

A table tennis club has N tables available to the public. The tables are numbered from 1 to N. For any pair of players, if there are some tables open when they arrive, they will be assigned to the available table with the smallest number. If all the tables are occupied, they will have to wait in a queue. It is assumed that every pair of players can play for at most 2 hours.
Your job is to count for everyone in queue their waiting time, and for each table the number of players it has served for the day.
One thing that makes this procedure a bit complicated is that the club reserves some tables for their VIP members. When a VIP table is open, the first VIP pair in the queue will have the priviledge to take it. However, if there is no VIP in the queue, the next pair of players can take it. On the other hand, if when it is the turn of a VIP pair, yet no VIP table is available, they can be assigned as any ordinary players.
Input Specification:
Each input file contains one test case. For each case, the first line contains an integer N (<=10000) - the total number of pairs of players. Then N lines follow, each contains 2 times and a VIP tag: HH:MM:SS - the arriving time, P - the playing time in minutes of a pair of players, and tag - which is 1 if they hold a VIP card, or 0 if not. It is guaranteed that the arriving time is between 08:00:00 and 21:00:00 while the club is open. It is assumed that no two customers arrives at the same time. Following the players’ info, there are 2 positive integers: K (<=100) - the number of tables, and M (< K) - the number of VIP tables. The last line contains M table numbers.
Output Specification:
For each test case, first print the arriving time, serving time and the waiting time for each pair of players in the format shown by the sample. Then print in a line the number of players served by each table. Notice that the output must be listed in chronological order of the serving time. The waiting time must be rounded up to an integer minute(s). If one cannot get a table before the closing time, their information must NOT be printed.
Sample Input:
9
20:52:00 10 0
08:00:00 20 0
08:02:00 30 0
20:51:00 10 0
08:10:00 5 0
08:12:00 10 1
20:50:00 10 0
08:01:30 15 1
20:53:00 10 1
3 1
2
Sample Output:
08:00:00 08:00:00 0
08:01:30 08:01:30 0
08:02:00 08:02:00 0
08:12:00 08:16:30 5
08:10:00 08:20:00 10
20:50:00 20:50:00 0
20:51:00 20:51:00 0
20:52:00 20:52:00 0
3 3 2

分析:
桌子的信息用优先队列存储,每次弹出空出来的桌子;
既然有两种玩家,那就设2个排队区,普通玩家队列和VIP玩家队列。根据两个队列的排队情况和空出的桌子是否是VIP桌的情况,来安排队列中的玩家进桌。
如果去的时候不用等位,普通玩家去编号最小的空桌子;VIP玩家去编号最小的空的VIP桌,如果没有空的VIP桌,就去编号最小的普通桌子。

#include <cstdio>using namespace std;#include <vector>#include <queue>#include <algorithm>struct Player {    int arriving_time; //到达时间     int playing_time; //打球的时长     int serving_time; //开始打球的时间     int tag; //是否VIP     int served; //是否打了球 };struct Table {    int num;    int end_time;    Table(int a, int b) :num(a), end_time(b) {}};bool compare1(Player x, Player y) {    return x.arriving_time < y.arriving_time;}bool compare2(Player x, Player y) {    if (x.served != y.served) return x.served > y.served;    else return x.serving_time < y.serving_time;}struct cmp {    bool operator()(const Table& x, const Table& y) {        if (x.end_time != y.end_time) return x.end_time > y.end_time;        else return x.num > y.num;    }};int main() {    int N;    scanf("%d", &N);    const int CLOSING = 21 * 3600;    const int OPENING = 8 * 3600;    vector<Player> V(N + 1);    for (int i = 1; i <= N; i++) {        int hh, mm, ss, play;        scanf("%d:%d:%d %d %d", &hh, &mm, &ss, &play, &V[i].tag);        V[i].arriving_time = 3600 * hh + 60 * mm + ss;        V[i].playing_time = play * 60;        if (V[i].playing_time > 7200) V[i].playing_time = 7200; //超过2小时的情况     }    sort(V.begin() + 1, V.end(), compare1);    int K, M;    scanf("%d %d", &K, &M);    vector<int> count(K + 1, 0); //number of players served by each table    vector<int> VIP(K + 1, 0); //标记是否为VIP桌     vector<int> serve(K + 1, 0); //桌子目前是否被占用     for (int i = 0; i < M; i++) {        int m;        scanf("%d", &m);        VIP[m] = 1;    }    priority_queue<Table, vector<Table>, cmp> PQ;    queue<int> Q_ordinary;    queue<int> Q_VIP;    int p1, p2;    int i = 1;    while (true) {        if (i <= N&&V[i].arriving_time >= CLOSING) break;        if (i > N&&Q_ordinary.empty() && Q_VIP.empty()) break; //所有人都处理完毕         if (PQ.size() == 0 || (PQ.size()<K&&V[i].arriving_time<PQ.top().end_time)) {   //去的时候有空桌子            V[i].serving_time = V[i].arriving_time>OPENING ? V[i].arriving_time : OPENING;            V[i].served = 1;            int minID = 0, minVIP = 0;            int m = 1;            for (m; m <= K; m++) {                if (serve[m] == 0) {                    minID = m;                    break;                }            }            if (V[i].tag == 1) { //如果是VIP,需要找空出的编号最小的VIP桌                for (m; m <= K; m++) {                    if (serve[m] == 0 && VIP[m] == 1) {                        minVIP = m;                        break;                    }                }            }            if (V[i].tag == 1 && minVIP > 0) {                PQ.push(Table(minVIP, V[i].serving_time + V[i].playing_time));                count[minVIP]++;                serve[minVIP] = 1;            }            else {                PQ.push(Table(minID, V[i].serving_time + V[i].playing_time));                count[minID]++;                serve[minID] = 1;            }            i++;            continue;        }        Table tmp = PQ.top();        if (tmp.end_time >= CLOSING) break;        if (i <= N&&V[i].arriving_time <= tmp.end_time) { //去的时候没有桌子空着,进入等待队列            if (V[i].tag) Q_VIP.push(i);            else Q_ordinary.push(i);            i++;            continue;        }        else { //去的时候有桌子空出来,当时还轮不到自己,暂时先不入队,处理队列中的人             Table tmp = PQ.top();            PQ.pop();            serve[tmp.num] = 0;            if (!Q_ordinary.empty() && Q_VIP.empty()) { //只有普通玩家                 p1 = Q_ordinary.front();                Q_ordinary.pop();                V[p1].serving_time = tmp.end_time;                V[p1].served = 1;                PQ.push(Table(tmp.num, tmp.end_time + V[p1].playing_time));                serve[tmp.num] = 1;                count[tmp.num]++;            }            else if (Q_ordinary.empty() && !Q_VIP.empty()) { //只有VIP玩家                 p2 = Q_VIP.front();                Q_VIP.pop();                V[p2].serving_time = tmp.end_time;                V[p2].served = 1;                PQ.push(Table(tmp.num, tmp.end_time + V[p2].playing_time));                serve[tmp.num] = 1;                count[tmp.num]++;            }            else if (!Q_ordinary.empty() && !Q_VIP.empty()) { //两种玩家都有。需要看当前空出的桌子是不是VIP桌                 p1 = Q_ordinary.front();                p2 = Q_VIP.front();                if (!VIP[tmp.num]) {                    if (V[p1].arriving_time < V[p2].arriving_time) {                        PQ.push(Table(tmp.num, tmp.end_time + V[p1].playing_time));                        serve[tmp.num] = 1;                        V[p1].serving_time = tmp.end_time;                        V[p1].served = 1;                        count[tmp.num]++;                        Q_ordinary.pop();                    }                    else {                        PQ.push(Table(tmp.num, tmp.end_time + V[p2].playing_time));                        serve[tmp.num] = 1;                        V[p2].serving_time = tmp.end_time;                        V[p2].served = 1;                        count[tmp.num]++;                        Q_VIP.pop();                    }                }                else {                    PQ.push(Table(tmp.num, tmp.end_time + V[p2].playing_time));                    serve[tmp.num] = 1;                    V[p2].serving_time = tmp.end_time;                    V[p2].served = 1;                    count[tmp.num]++;                    Q_VIP.pop();                }            }        }    }    sort(V.begin() + 1, V.end(), compare2);    for (int i = 1; i <= N; i++) {        if (V[i].served == 0) break;        printf("%02d:%02d:%02d ", V[i].arriving_time / 3600, V[i].arriving_time / 60 % 60, V[i].arriving_time % 60);        printf("%02d:%02d:%02d ", V[i].serving_time / 3600, V[i].serving_time / 60 % 60, V[i].serving_time % 60);        int waiting_time = (V[i].serving_time - V[i].arriving_time) / 60;        if ((V[i].serving_time - V[i].arriving_time) % 60 >= 30) waiting_time++;        printf("%d\n", waiting_time);    }    for (int i = 1; i < K; i++) {        printf("%d ", count[i]);    }    printf("%d\n", count[K]);    return 0;}//http://blog.csdn.net/jmlikun/article/details/49821845
0 0