又是复杂模拟题。。。再度奉上大神代码
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<iostream>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
typedef long long LL;
const int INF = 0x7FFFFFFF;
const int maxn = 1e5 + 10;
int n, f[maxn], t[maxn], x, y, z, m, u, vis[maxn], cnt[maxn];
struct point
{
int x, y, f;
bool operator<(const point &a)const
{
return x < a.x;
}
}a[maxn];
void putout(int x)
{
printf("%02d:%02d:%02d ", x / 3600, x / 60 % 60, x % 60);
}
void putmin(int x)
{
printf("%d\n", x / 60 + (x % 60 < 30 ? 0 : 1));//满30秒进1分
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d:%d:%d", &x, &y, &z);
a[i].x = x * 3600 + y * 60 + z;
scanf("%d%d", &x, &a[i].f);
a[i].y = min(x * 60, 7200);//最多不超过2小时
}
sort(a, a + n);
scanf("%d%d", &m, &u);
while (u--) scanf("%d", &x), f[x] = 1;
for (int i = 1; i <= m; i++) t[i] = 8 * 3600;
for (int i = 0; i < n; i++)
if (!vis[i])
{
int now = 1;
for (int j = 1; j <= m; j++) if (t[now] > t[j]) now = j;//找出最早空出的桌子
if (max(t[now], a[i].x) >= 21 * 3600) break;//超过21点跳出
if (t[now] <= a[i].x)//这意味着现在不用排队
{
int vip = -1;//如果这个人是vip那么会选择能用的vip的桌子中最小的
for (int j = m; j >= 1; j--)
{
if (t[j] <= a[i].x) now = j;
if (t[j] <= a[i].x&&f[j]) vip = j;
}
if (a[i].f&&vip != -1) now = vip; //如果这个人是vip且有vip的桌子能用
cnt[now]++;
putout(a[i].x); putout(a[i].x);
printf("0\n"); t[now] = a[i].x + a[i].y;
}
else//这意味着现在有人在排队
{
/*这部分有个问题
如果有人在排队,并且同时空出了一张非vip桌子和一张vip桌子,
如果标号小的不是vip,标号大的是vip,那么先处理哪个呢,题目没有明确的指出
经过我的测试,也没有这样的数据,所以可以忽略。
int vip = -1; //如果有vip桌子同时也可用
for (int j = m; j >= 1; j--)
{
if (t[j] == t[now] && f[j]) vip = j;
}
if (vip != -1)//先选择处理vip桌子
{
int flag = 0;
for (int j = i; j < n&&a[j].x <= t[vip]; j++)
{
if (a[j].f&&!vis[j])
{
vis[j] = 1;
putout(a[j].x); putout(t[vip]);
putmin(t[vip] - a[j].x);
t[vip] = t[vip] + a[j].y;
flag = 1; break;
}
}
if (flag) { cnt[vip]++; i--; continue; }
}
*/
cnt[now]++;
if (f[now]) //如果是vip的桌子
{
int flag = 0;
for (int j = i; j < n&&a[j].x <= t[now]; j++)//找到是否有vip在等待
{
if (a[j].f&&!vis[j])
{
vis[j] = 1;
putout(a[j].x); putout(t[now]);
putmin(t[now] - a[j].x);
t[now] = t[now] + a[j].y;
flag = 1; break;
}
}
if (flag) i--;
else//如果没有,那么第一个人用了
{
putout(a[i].x); putout(t[now]);
putmin(t[now] - a[i].x);
t[now] = t[now] + a[i].y;
}
}
else//非vip桌子,直接用
{
putout(a[i].x); putout(t[now]);
putmin(t[now] - a[i].x);
t[now] = t[now] + a[i].y;
}
}
}
for (int i = 1; i <= m; i++) printf("%d%s", cnt[i], i == m ? "\n" : " ");
return 0;
}