5-30 Table Tennis (30分)

原題

一看就是模擬題, 但就是有些細節有點繁瑣..
題意大概是維護一些桌子, 有人來的時候如果有桌子就分配,沒有桌子就讓他們等待下一張空閒的桌子。

只不過還有一些特殊的VIP桌子和VIP用戶,如果當前有空閒的VIP桌子,那就優先分配給已經到達的且當前正在等待隊列中的那些VIP用戶。若沒有空閒的VIP桌子則VIP用戶視爲普通用戶處理。

我的主要思路就是按時間點(currentTime)推進的順序來逐一處理事件。到達一個新的時間點的時候,首先檢查是否可以把VIP桌子分配給VIP用戶。之後檢查普通的桌子是否能夠分配給哪個用戶。第三步就是更新時間點currentTime爲下一個需要進行處理的時間點。

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <cctype>
#include <stack>
#include <list>
#include <vector>
#include <algorithm>

using namespace std;

const int StartTime = 8 * 60 * 60, EndTime = 21 * 60 * 60;

/*
計算過程中的時間均以秒爲單位
*/

struct Pair {
    int arriveTime;
    int beginTime;
    int playTime;               // 將要玩的時間(以秒爲單位, 【等於0則已經玩過】)
    int waitTime;               // 等待的時間
    bool isVip;
    Pair (int _a = 0, int _b = 0, bool _is = 0) : arriveTime (_a), playTime (_b), isVip(_is) { 
        beginTime = waitTime = 0; 
    }
};

int N, M, tblNum;
list<Pair> players;
int AvailableTime[101];             // 標記桌子下一次能用的時間
int Served[101];                                // 標記桌子用過次數
vector<int> vipTable;

bool CompByArrive (const Pair & p1, const Pair & p2) {
    return p1.arriveTime < p2.arriveTime;
}

bool CompByBegin (const Pair & p1, const Pair & p2) {
    return p1.beginTime < p2.beginTime;
}

int TimeToInt (char times[]) {
    int tmp = 0;
    char * result = strtok (times, ":");
    tmp += atoi (result) * 60;
    result = strtok (NULL, ":");
    tmp = (tmp + atoi (result) ) * 60;
    result = strtok (NULL, ":");
    tmp += atoi (result);
    return tmp;
}

string IntToTime (int time) {
    char result[20];
    int hour = time / ( 60 * 60 );
    time -= hour * 60 * 60;
    int minute = time / 60;
    time -= minute * 60;
    sprintf (result, "%02d:%02d:%02d", hour, minute, time);
    return string(result);
}

int nextPlayerTime ( ) {
    int earliest = EndTime;
    for ( auto it = players.begin ( ); it != players.end ( ); it++) {
        if( it->playTime > 0 )  earliest = min (it->arriveTime, earliest);
    }
    return earliest;
}

void SetPlayer (Pair & player, int tbl, int currentTime) {
    AvailableTime[tbl] = currentTime + min (player.playTime, 2 * 60 * 60);      // 最多用2小時
    player.beginTime = currentTime;
    player.waitTime = currentTime - player.arriveTime;
    player.playTime = 0;
    Served[tbl]++;
}

int main ( ) {
    char strings[20];
    int playtime, isVIP;
    Pair player;
    // 讀入數據
    cin >> N;
    for ( int i = 1; i <= N; i++ ) {
        cin >> strings >> playtime >> isVIP;
        players.push_back (Pair (TimeToInt (strings), playtime * 60, isVIP));
    }
    cin >> tblNum >> M;
    for ( int i = 0, tmp; i < M; i++) {
        cin >> tmp;
        vipTable.push_back (tmp);
    }

    // 模擬
    int currentTime = StartTime;
    list<Pair>::iterator it_player;
    for ( int i = 1; i <= tblNum; i++){
        AvailableTime[i] = StartTime;
    }

    players.sort(CompByArrive);
    do {
        // 找VIP桌子
        for ( int i = 0; i < vipTable.size ( ); i++ ) {
            if ( AvailableTime[vipTable[i]] <= currentTime ) {
                for ( it_player = players.begin ( ); it_player != players.end ( ); it_player++ ) {
                    if ( it_player->isVip && it_player->arriveTime <= currentTime && it_player->playTime > 0  ) {
                        SetPlayer (*it_player, vipTable[i], currentTime);
                        break;                          // 注意分配完一張桌子一定要及時break否則繼續找Pair很可能會再分配這張桌子第二次
                    }
                }
            }
        }
        // 找普通桌子
        for ( int i = 1; i <= tblNum; i++ ) {
            if ( AvailableTime[i] <= currentTime ) {
                for ( it_player = players.begin ( ); it_player != players.end ( ); it_player++ ) {
                    if ( it_player->playTime > 0 && it_player->arriveTime <= currentTime ) {
                        SetPlayer (*it_player, i, currentTime);
                        break;
                    }
                }
            }
        }
        // 更新下一次的時間
        currentTime = EndTime;
        for ( int i = 1; i <= tblNum; i++) {
            currentTime = min (currentTime, AvailableTime[i]);
        }
        currentTime = max (currentTime, nextPlayerTime ( ));
    } while ( currentTime < EndTime );

    players.sort (CompByBegin);
    for ( it_player = players.begin ( ); it_player != players.end ( ); it_player++) {
        if ( it_player->playTime == 0 ) {
            cout << IntToTime (it_player->arriveTime) << " " << IntToTime (it_player->beginTime) << " " <<
                ( it_player->waitTime + 30 )/ 60 << endl;
        }
    }
    for ( int i = 1; i <= tblNum; i++ ) {
        cout << Served[i] << ( i < tblNum ? " " : "\n" );
    }
    system ("pause");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章