一看就是模拟题, 但就是有些细节有点繁琐..
题意大概是维护一些桌子, 有人来的时候如果有桌子就分配,没有桌子就让他们等待下一张空闲的桌子。
只不过还有一些特殊的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");
}