题意:
一个乒乓球俱乐部有N张乒乓球桌对外开放。乒乓球桌编号为1 ~ N。对任何一对运动员,如果他们到达时有空余的乒乓球桌,他们会被分配到可用的编号最小的那张乒乓球桌。如果所有的桌子都被占了,他们必须在队列中等待。假设任何一对运动员最多只能占用球桌2小时。
你的任务是为每个人计算他们在队列中的等待时间,以及每张球桌一天服务的运动员数量。
由于俱乐部为他们的VIP会员保留了一些VIP球桌,这使得这件事情变得稍微复杂了些。当一张VIP球桌对外开放时,队列中的第一对VIP运动员将优先享有这张球桌的使用权。然而,如果队列中没有VIP运动员,下一对运动员可以使用这张球桌。另外,如果轮到了VIP运动员,但是没有任何VIP球桌是可用的,他们就会像普通运动员一样被安排
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
struct person {
int arrive, start, time;
bool vip;
} tempperson;
struct tablenode {
int end = 8 * 3600, num;
bool vip;
};
bool cmp1(person a, person b) {
return a.arrive < b.arrive;
}
bool cmp2(person a, person b) {
return a.start < b.start;
}
vector<person> player;
vector<tablenode> table;
void alloctable(int personid, int tableid) {
if(player[personid].arrive <= table[tableid].end)//玩家到达时间早于桌子空闲时间
player[personid].start = table[tableid].end;
else
player[personid].start = player[personid].arrive;
table[tableid].end = player[personid].start + player[personid].time;
table[tableid].num++;
}
int findnextvip(int vipid) {
vipid++;
while(vipid < player.size() && player[vipid].vip == false) {
vipid++;
}
return vipid;
}
int main() {
int n, k, m, viptable;
scanf("%d", &n);
for(int i = 0; i < n; i++) {
int h, m, s, temptime, flag;
scanf("%d:%d:%d %d %d", &h, &m, &s, &temptime, &flag);
tempperson.arrive = h * 3600 + m * 60 + s;
tempperson.start = 21 * 3600;
if(tempperson.arrive >= 21 * 3600)
continue;
tempperson.time = temptime <= 120 ? temptime * 60 : 7200;
tempperson.vip = ((flag == 1) ? true : false);
player.push_back(tempperson);
}
scanf("%d%d", &k, &m);
table.resize(k + 1);
for(int i = 0; i < m; i++) {
scanf("%d", &viptable);
table[viptable].vip = true;
}
sort(player.begin(), player.end(), cmp1);
int i = 0, vipid = -1;
vipid = findnextvip(vipid);
while(i < player.size()) {
int index = -1, minendtime = 999999999;
for(int j = 1; j <= k; j++) {//找最先空出来的桌子
if(table[j].end < minendtime) {
minendtime = table[j].end;
index = j;
}
}
if(table[index].end >= 21 * 3600)
break;//健身馆关门
// if(player[i].vip == true && i < vipid) {
// i++;//前面已经出现过了
// continue;
// }
if(table[index].vip == true) {//最先空出来的桌子是VIP桌子
if(player[i].vip == true) {
alloctable(i, index);//VIP人员分配VIP桌子
if(vipid == i)
vipid = findnextvip(vipid);
i++;
} else {//非VIP人员,将VIP桌子分配给队列中VIP人员
if(vipid < player.size() && player[vipid].arrive <= table[index].end) {
alloctable(vipid, index);
vipid = findnextvip(vipid);
} else {//队列中无VIP人员,则分配给普通人员
alloctable(i, index);
i++;
}
}
} else {
if(player[i].vip == false) {//非VIP人员直接分配普通桌子
alloctable(i, index);
i++;
} else {//VIP人员分配最早空闲的VIP桌子
int vipindex = -1, minvipendtime = 999999999;
for(int j = 1; j <= k; j++) {
if(table[j].vip == true && table[j].end < minvipendtime) {
minvipendtime = table[j].end;
vipindex = j;
}
}//若存在最早的VIP空闲桌子
if(vipindex != -1 && player[i].arrive >= table[vipindex].end) {
alloctable(i, vipindex);
if(vipid == i)
vipid = findnextvip(vipid);
i++;
} else {//不存在最早空闲的VIP桌子,找到分配最先空闲的普通桌子
alloctable(i, index);
if(vipid == i)
vipid = findnextvip(vipid);
i++;
}
}
}
}
sort(player.begin(), player.end(), cmp2);
for(i = 0; i < player.size() && player[i].start < 21 * 3600; i++) {
printf("%02d:%02d:%02d ", player[i].arrive / 3600, player[i].arrive % 3600 / 60, player[i].arrive % 60);
printf("%02d:%02d:%02d ", player[i].start / 3600, player[i].start % 3600 / 60, player[i].start % 60);
printf("%.0f\n", round((player[i].start - player[i].arrive) / 60.0));
}
for(int i = 1; i <= k; i++) {
if(i != 1)
printf(" ");
printf("%d", table[i].num);
}
return 0;
}