[PAT] A1026 Table Tennis

tech2022-09-05  101

(繁)

题目大意

有若干乒乓球桌(编号1到N)和最多能玩2小时的玩家,若空闲则到达的人选择编号最小的乒乓球桌,若桌被占满了则排队。有VIP玩家和VIP球桌,若VIP球桌有空,则排在最前面的VIP玩家上桌,若没有VIP,则队首普通玩家上桌。轮到VIP玩家时,不是VIP桌也会上桌。8点到21点开业。 现给出每个人到达的时间、占桌时长(min)、是否VIP,以及桌子总数和VIP桌子数,VIP桌子编号。按照服务时间先后顺序输出每个人到达时间、得到服务时间、等待时长(以分钟单位取整),每桌服务人数。注意:如果这个人在得到服务时超过了21点,则不输出。

tips

1

e--计算结果 a--被除数 b--除数 1(四舍五入) : e=(a+(b/2))/b 2(进一法) : e=(a+(b-1))/b

2

vector容器的v.resize(int n,element)函数。 调整容器v大小为n;扩容后每个元素值为element,缺省为0。

测试点4

如果输入的时长超过2小时的,要手动缩短成2小时。

测试点5、7

当有多个桌子空闲时,且空闲的里面有vip桌时,vip用户会选择编号最小的vip桌,即使有空闲的、编号更小的普通桌。如果空闲的里面没有vip桌,vip用户选择编号最小的桌。

测试点8

超时,不知道为啥

#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include<vector> #include<algorithm>/// #include<iostream> using namespace std; #define N 10000 #define K 102 #define CLOSE 21 * 60 * 60 struct people { int arrive; int serve; int occupy; bool vip; }player[N + 1]; int tend[K];//该桌子当前最早结束使用时间 int Ptable[K] = { 0 };//记录每张桌子服务人数 int ifserve[N + 1] = { 0 };//标记该客户是否被服务, 0未服务,负数判断将不会服务 vector<people>pans; void fenpei(int ren, int zhuo) { player[ren].serve = tend[zhuo] < player[ren].arrive ? player[ren].arrive : tend[zhuo]; if (player[ren].serve < CLOSE) { ifserve[ren] = 1; pans.push_back(player[ren]); tend[zhuo] = player[ren].serve + player[ren].occupy; Ptable[zhuo]++; } } //找到最早结束的桌子编号 int findmin(int a[], int k) { int min = 1; for (int i = 2;i <= k;i++) { if (a[i] < a[min]) min = i; } return min; } //找到最早结束的VIP桌子编号 int findvipmin(int a[], int k, bool vip[]) { int time = CLOSE + 2 * 60 * 60 + 1; int min = -1; for (int i = 1;i <= k;i++) { if (vip[i] == 0) continue; if (a[i] < time) { min = i; time = a[i]; } } return min; } bool cmp_arrive(people a, people b) { return a.arrive < b.arrive; } bool cmp_serve(people a, people b) { return a.serve < b.serve; } int main() { int n; int k;//桌子数 int m;//vip桌子数 bool VIPtable[K] = { 0 };//是否为VIP桌子 int i, j; //输入 剔除到达时间>=21点的 scanf("%d", &n); for (i = 0;i < n;i++) { int a, b, c; scanf("%d:%d:%d", &a, &b, &c); player[i].arrive = a * 60 * 60 + b * 60 + c; int temptime; scanf("%d%d", &temptime, &player[i].vip); player[i].occupy = temptime > 120 ? 120 * 60 : temptime * 60; if (player[i].arrive >= CLOSE) { i--; n--; } //player[i].wait = 0; } scanf("%d%d", &k, &m); for (i = 1;i <= k;i++) tend[i] = 8 * 60 * 60; for (i = 0;i < m;i++) { int temp; scanf("%d", &temp); VIPtable[temp] = 1; } sort(player, player + n, cmp_arrive); //计算服务时间 for (i = 0;i < n;i++) { if (ifserve[i] != 0)continue;//过滤掉提前处理的VIP j = findmin(tend, k);//寻找最早结束编号最小的桌子 if (tend[j] > CLOSE)break; //当第i个人来时,先判断是否是VIP if (player[i].vip) {//是VIP if (VIPtable[j]) fenpei(i, j); //桌是VIP桌,直接分配 else {//桌非VIP if (tend[j] <= player[i].arrive) {//空桌不是VIP且人到时桌空,再找找有没有空VIP桌 int u = findvipmin(tend, k, VIPtable); if (u > 0 && tend[u] <= player[i].arrive) {//若人到时VIP桌空,则分配 fenpei(i, u); } else fenpei(i, j); } else fenpei(i, j); } } else {//队首不是VIP if (VIPtable[j] && tend[j] > player[i].arrive) { //桌是VIP桌且人要等,则看看后后面有没有VIP用户 int v = i; for (;v < n;v++) { if (player[v].vip)break; } if (v == n) fenpei(i, j);//后面没VIP了,队首普通用户上桌 else { fenpei(v, j);//否则VIP插队 i--;//下一次循环还处理队首非VIP } } else fenpei(i, j); } } sort(pans.begin(), pans.end() , cmp_serve); for (i = 0;i < pans.size();i++) { int hh, mm, ss; hh = pans[i].arrive / 3600; mm = (pans[i].arrive - hh * 3600) / 60; ss = pans[i].arrive - hh * 3600 - mm * 60; printf("%02d:%02d:%02d ", hh, mm, ss); hh = pans[i].serve / 3600; mm = (pans[i].serve - hh * 3600) / 60; ss = pans[i].serve - hh * 3600 - mm * 60; printf("%02d:%02d:%02d ", hh, mm, ss); //printf("***%d*** ", player[i].vip); printf("%d\n", (pans[i].serve - pans[i].arrive + 30) / 60); } for (i = 1;i <= k;i++) { if (i != 1)printf(" "); printf("%d", Ptable[i]); } return 0; }

AC代码

参考了 (https://blog.csdn.net/a1552100455/article/details/100060101)

#include<iostream> #include<vector> #include<algorithm> #include<math.h> using namespace std; struct person { int come, get, play, wait; bool isvip = false; }pperson; struct table { bool isvip = false; int present = 8 * 3600;//当前该桌结束使用时间 int num = 0; }; vector<person> vec, res;//res存放被服务的人 vector<table> tables;//角标就是编号 //所有人中最早到的VIP脚标 int getVIP(int index) { index++; while (index < vec.size() && vec[index].isvip == false) index++; return index; } void alloac(int p, int t) { vec[p].get = tables[t].present < vec[p].come ? vec[p].come : tables[t].present; if (vec[p].get < 21 * 3600) { res.push_back(vec[p]); tables[t].num++; tables[t].present = vec[p].get + vec[p].play; } } bool cmp_come(person p1, person p2) { return p1.come < p2.come; } bool cmp_get(person p1, person p2) { return p1.get < p2.get; } int main() { int n, k, p; scanf("%d", &n); for (int i = 0; i < n; i++) { int hour, min, sec, play, flag; scanf("%d:%d:%d %d %d", &hour, &min, &sec, &play, &flag); pperson.come = hour * 3600 + min * 60 + sec; pperson.get = 21 * 3600; if (pperson.come >= 21 * 3600) continue; pperson.play = play > 120 ? 120 * 60 : play * 60; pperson.isvip = flag; vec.push_back(pperson); } scanf("%d %d", &k, &p); tables.resize(k + 1); for (int i = 0; i < p; i++) { int temp; scanf("%d", &temp); tables[temp].isvip = true; } sort(vec.begin(), vec.end(), cmp_come); int i = 0; int vipid = getVIP(-1); while (i < vec.size()) { int min = 999999999, index = -1; for (int j = 1; j < tables.size(); j++) { if (tables[j].present < min) { min = tables[j].present; index = j; } }//找最早结束的桌子index if (tables[index].present >= 21 * 3600) break; if (vec[i].isvip == true && i < vipid) { i++; continue; } if (tables[index].isvip == true) {//会员桌子 //先检查会员 插队 if (vec[i].isvip == true) {//队头就是会员 alloac(i, index); vipid = getVIP(vipid); i++; } else { if (vipid < vec.size() && vec[vipid].come <= tables[index].present) {//看看队里有没有会员 alloac(vipid, index); vipid = getVIP(vipid); } else {//没有会员 alloac(i, index); i++; } } } else {//普通桌子 int mintemp = 999999999; int tempindex = -1; if (vec[i].isvip == true) {//第一个人是VIP for (int k = 1; k < tables.size(); k++) { if (tables[k].isvip && tables[k].present < mintemp) { mintemp = tables[k].present; tempindex = k; } } if (tempindex != -1 && tables[tempindex].present <= vec[i].come) {//有会员桌子 插队 alloac(i, tempindex); vipid = getVIP(vipid); i++; } else {//没有会员桌子 那就跟普通人一样 alloac(i, index); vipid = getVIP(vipid); i++; } } else {//普通人 alloac(i, index); i++; } } } sort(res.begin(), res.end(), cmp_get); for (int i = 0; i < res.size(); i++) { printf("%02d:%02d:%02d ", res[i].come / 3600, res[i].come % 3600 / 60, res[i].come % 60); printf("%02d:%02d:%02d %.0f\n", res[i].get / 3600, res[i].get % 3600 / 60, res[i].get % 60, round((res[i].get - res[i].come) / 60.0)); } printf("%d", tables[1].num); for (int i = 2; i < tables.size(); i++) printf(" %d", tables[i].num); return 0; }

仔细比对了自己写的代码,比了好久都不知道复杂在了哪......如果有好心的大佬帮忙解答一下,感激不尽。 在我看来我们的区别是我是先看第一个人再看第一张桌,AC代码是先看桌再看人。

最新回复(0)