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");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章