将排队的人按照到达的时间排序,然后开始轮询,会有四种情况:
- 桌子是VIP,人是VIP,则直接分配
- 桌子不是VIP,人也不是VIP,则直接分配
- 桌子是VIP,人不是VIP,则往后找,是否存在一个VIP,且其到达时间早于该桌子的可用时间,找到则给VIP,当前的人继续等待,找不到这样的VIP,则把该桌子给当前用户
- 桌子不是VIP,人是VIP,则检查桌子,是否还存在一张VIP桌子也空闲着,如果有这样一张VIP桌子,则将VIP桌子分给该VIP用户,如果没有VIP桌子闲着,则该VIP用该桌子。
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <tuple>
using namespace std;
#define INF (~(1<<31))
struct Player{
int arrive, play, serve, leave, wait, tag;
Player(int a, int p, int t) : arrive(a), play(p), serve(INF), leave(INF), wait(INF), tag(t){}
bool operator < (const Player& rhs) const{
return arrive < rhs.arrive;
}
};
struct Table{
int leave;
int cnt;
int tag;
Table() : leave(8 * 3600), cnt(0), tag(0){}
};
int time2sec(int hh, int mm, int ss){
return hh * 3600 + mm * 60 + ss;
}
tuple<int,int,int> sec2time(int n){
return make_tuple(n/3600, (n%3600)/60, (n%3600)%60);
}
int main(){
int n;
scanf("%d", &n);
vector<Player> users;
for (int i = 0; i < n; ++i){
int hh, mm, ss, p, tag;
scanf("%d:%d:%d %d %d", &hh, &mm, &ss, &p, &tag);
users.emplace_back(time2sec(hh, mm, ss), min(p*60, 2*60*60), tag);
}
sort(begin(users), end(users));
int k, m;
scanf("%d%d", &k, &m);
vector<Table> tables(k);
for (int i = 0; i < m; ++i){
int num;
scanf("%d", &num); num--;
tables[num].tag = 1;
}
int i;
for (i = 0; i < n; ++i){
// if the player has been processed, continue
if (users[i].serve != INF) continue;
// find the available table with the smallest number
int j = -1, minLeave = INF;
for (int x = 0; x < k; ++x){
if (minLeave > tables[x].leave){
minLeave = tables[x].leave;
j = x;
}
}
// if the minLeave table >= 21:00:00 or the current player's arrive time >= 21:00:00, break;
if(tables[j].leave >= 21*3600 || users[i].arrive >= 21*3600) break;
int u = i, t = j;
// table is vip && player is not vip
if (tables[j].tag && !users[i].tag){
int ii = -1;
for (int x = i + 1; x < n; ++x){
if (users[x].serve == INF && users[x].tag && users[x].arrive <= tables[j].leave){
ii = x;
break;
}
}
if(ii != -1){
--i; // the current player need wait
u = ii;
}
}else if (!tables[j].tag && users[i].tag){ // table is not vip && player is vip
int jj = t;
for (int x = j + 1; x < k; ++x){
if (tables[x].tag && tables[x].leave <= users[i].arrive){
jj = x;
break;
}
}
t = jj;
}
if (tables[t].leave < users[u].arrive){
tables[t].leave = users[u].arrive + users[u].play;
}
else{
tables[t].leave += users[u].play;
}
users[u].leave = tables[t].leave;
users[u].serve = users[u].leave - users[u].play;
users[u].wait = users[u].serve - users[u].arrive;
tables[t].cnt++;
}
sort(begin(users), end(users), [](const Player& lhs, const Player& rhs){
if (lhs.serve != rhs.serve) return lhs.serve < rhs.serve;
else return lhs.arrive < rhs.arrive;
});
for (size_t i = 0; i < users.size(); ++i){
if (users[i].serve > 21 * 3600) continue;
int hh1, mm1, ss1, hh2, mm2, ss2;
tie(hh1, mm1, ss1) = sec2time(users[i].arrive);
tie(hh2, mm2, ss2) = sec2time(users[i].serve);
int w = (int)round(users[i].wait / 60.0);
printf("%02d:%02d:%02d %02d:%02d:%02d %d\n", hh1, mm1, ss1, hh2, mm2, ss2, w);
}
for(size_t i = 0; i < tables.size(); ++i){
if(i) printf(" ");
printf("%d", tables[i].cnt);
}
return 0;
}