思路
这题好难啊…尤其是测试点非常坑。我在牛客网上测试用例都通过了,但是在PAT上最后一个用例到现在也还没通过,不知道是哪里出了问题。
目前发现的坑点:
1、每个玩家占用时间不能超过两小时,超过两小时按两小时算。其实题目里没有明确地要求判断,但它既然都说了,那这么奇怪的一句话肯定是一个测点。应该是用例4。判断之后,用例4就通过了。
2、当有多个桌子空闲时,且空闲的里面有vip桌时,vip用户会选择编号最小的vip桌,即使有空闲的、编号更小的普通桌。如果空闲的里面没有vip桌,vip用户选择编号最小的桌。
3、等待时间四舍五入。round函数即可。
这两点考虑之后我就只剩下最后一个测点没法通过了。最后得分29/30,如果有大佬能帮忙看看我的代码哪里出错了,将不甚感激!!!
当然还有其他的一些问题,但是基本上会在给出的样例测点里体现出来,比如超过21点不服务等等,就不多说了。
我是这么考虑的,先记录所有人的信息和桌子的信息。
桌子维护三个数组,一个是vip[ ],记录该桌是否为vip桌,一个是table[ ],记录该桌即将空闲的时间,初始化为8*3600(早上八点),一个是number[ ],记录每桌服务人数。
人表示成Pair结构体,维护两个容器,一个是vector<Pair>pairs,记录所有人的信息,一个是queue<int>vpairs,记录vip用户在pairs中的下标。均按到达时间排序。
过程如下:
初始化各类信息。然后遍历已按到达时间排好序的vector<Pair> pairs。
如果是vip用户,调用findEarlyTableForVip函数,它是找到即将最早空闲/或者在该用户到达时处于空闲状态的所有(可能有多个)桌子中的vip桌,如果这批即将最早空闲/或者在该用户到达时处于空闲状态的桌子里没有vip桌,则返回0,否则返回编号最小的那张空闲的vip桌子编号。回到主函数,判断如果findEarlyTableForVip不为0,则将返回值的桌子编号分配给这个vip用户,更新各类信息。如果为0,则调用findEarlyTable函数,这个函数就是找到即将最早空闲/或者在该用户到达时处于空闲状态的编号最小的桌子,不管它是普通桌还是vip桌。那么这个函数的返回值的桌子编号就分配给这个vip用户(这个vip用户在当前没有空闲vip桌的情况下坐上了普通桌),更新各类信息。
如果是普通用户,调用findEarlyTableForCommon函数,这个函数是为普通用户分配桌子的,返回最合适的桌子。这个函数的主体是一个循环,先看看vpairs(记录了vip用户在pairs中的下标,是按到达时间排序的,如果最前面的vip用户已分配,则pop,所以它的队头永远是下一个待分配的vip用户)是否为空,如果为空,代表没有vip用户了,普通用户可以为所欲为,直接调用findEarlyTable函数找到最合适的桌子,返回,然后回到主函数更新各类信息。如果不为空,那么在为这个普通用户分配桌子前,要照顾vip用户,调用findEarlyTableForVip,如果发现有空闲的vip桌并且当前第一个vip的到达时间是早于这个vip桌的,那么为这个vip分配(记得给这个vip打一个标记,因为后面再处理到它时就要跳过),并且更新各类信息。然后continue,直到没有符合条件的vip,这时就再调用findEarlyTable为这个普通用户找张桌子,返回,回到了主函数更新各类信息。
程序还维护了一个vector<int> servingSquence,每当为一个用户分配桌子,并且分配时间在21:00以前,那么将它的下标push进去。最后按照这个vector里的顺序打印结果即可。
牛客网上的这题测点都过了,但是PAT的最后一个测点过不了,不知道为啥…反复想了很多遍,也不知道哪里有漏洞。后来我按照别人的方法仿写过,过了,但是我自己写的代码却总有一个测点过不了,而且想不出原因,这让人寝食难安啊啊。希望有大佬可以帮助我。
#include<stdio.h>
#include<vector>
#include<queue>
#include<math.h>
#include<algorithm>
using namespace std;
struct Pair
{
int arr;
int ser;
int duration;
int tag;
};
bool vip[101];
int number[101];
int table[101];
vector<Pair> pairs;
queue<int> vpairs;
vector<int> servingSquence;
bool cmp(Pair p1, Pair p2)
{
return (p1.arr < p2.arr);
}
void init()
{
for (int i = 0; i < 101; i++)
{
vip[i] = false;
number[i] = 0;
table[i] = 8 * 3600;
}
}
int findEarlyTableForVip(int K, int arr)
{
vector<int> candidate;
int ans = 1000000;
for (int i = 1; i <= K; i++)
{
if (table[i] <= arr)
{
if (ans > arr)
{
candidate.clear();
}
ans = -1;
candidate.push_back(i);
}
if (table[i] < ans)
{
candidate.clear();
candidate.push_back(i);
ans = table[i];
}
else if (table[i] == ans)
{
candidate.push_back(i);
}
}
for (int i = 0; i < candidate.size(); i++)
{
if (vip[candidate[i]] == true)
{
return candidate[i];
}
}
return 0;
}
int findEarlyTable(int K, int arr)
{
int res = 0;
int ans = 1000000;
for (int i = 1; i <= K; i++)
{
if (table[i] <= arr)
{
res = i;
break;
}
if (table[i] < ans)
{
ans = table[i];
res = i;
}
}
return res;
}
int findEarlyTableForCommon(int K, int arr)
{
while (1)
{
if (vpairs.empty() == true)
{
return findEarlyTable(K, arr);
}
else
{
int candidate = findEarlyTableForVip(K, arr);
if (candidate != 0 && pairs[vpairs.front()].arr <= table[candidate])
{
int tmp = vpairs.front();
pairs[tmp].tag = -1;
pairs[tmp].ser = table[candidate];
vpairs.pop();
if (pairs[tmp].ser < 21 * 3600)
{
number[candidate]++;
servingSquence.push_back(tmp);
}
table[candidate] += pairs[tmp].duration;
continue;
}
}
return findEarlyTable(K, arr);
}
}
int main()
{
int N;
scanf("%d", &N);
for (int i = 0; i < N; i++)
{
int h, m, s;
Pair p;
scanf("%d:%d:%d %d %d", &h, &m, &s, &p.duration, &p.tag);
// 用例4
if (p.duration > 120)
{
p.duration = 120;
}
p.duration *= 60;
p.arr = h * 3600 + m * 60 + s;
pairs.push_back(p);
}
sort(pairs.begin(), pairs.end(), cmp);
for (int i = 0; i < N; i++)
{
if (pairs[i].tag == 1)
{
vpairs.push(i);
}
}
int K, M;
scanf("%d%d", &K, &M);
for (int i = 1; i <= M; i++)
{
int t;
scanf("%d", &t);
vip[t] = true;
}
for (int i = 0; i < N; i++)
{
if (pairs[i].tag == -1)
{
continue;
}
if (pairs[i].tag == 1)
{
int bestTable = findEarlyTableForVip(K, pairs[i].arr);
if (bestTable == 0)
{
bestTable = findEarlyTable(K, pairs[i].arr);
}
pairs[i].ser = (pairs[i].arr < table[bestTable]) ? table[bestTable] : pairs[i].arr;
if (pairs[i].ser < 21 * 3600)
{
number[bestTable]++;
servingSquence.push_back(i);
}
table[bestTable] = pairs[i].ser + pairs[i].duration;
vpairs.pop();
}
else
{
int bestTable = findEarlyTableForCommon(K, pairs[i].arr);
pairs[i].ser = (pairs[i].arr < table[bestTable]) ? table[bestTable] : pairs[i].arr;
if (pairs[i].ser < 21 * 3600)
{
number[bestTable]++;
servingSquence.push_back(i);
}
table[bestTable] = pairs[i].ser + pairs[i].duration;
}
}
for (int j = 0; j < servingSquence.size(); j++)
{
int i = servingSquence[j];
if (pairs[i].ser >= 21 * 3600)
{
continue;
}
else
{
int arrive = pairs[i].arr;
int serve = pairs[i].ser;
int wait = round(float(pairs[i].ser - pairs[i].arr) / 60.0);
printf("%02d:%02d:%02d %02d:%02d:%02d %d\n",
arrive / 3600, (arrive % 3600) / 60, arrive % 3600 % 60,
serve / 3600, (serve % 3600) / 60, serve % 3600 % 60, wait);
}
}
for (int i = 1; i <= K; i++)
{
if (i == 1)
{
printf("%d", number[i]);
continue;
}
printf(" %d", number[i]);
}
return 0;
}