zoukankan      html  css  js  c++  java
  • [PAT] A1026 Table Tennis

    (繁)

    题目大意

    有若干乒乓球桌(编号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
    ", (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
    ", 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代码是先看桌再看人。

  • 相关阅读:
    BLE编程中关键步骤
    gradle相关配置内容解析
    Gradle版本变更的问题
    【问题】AndroidStudio导入项目一直卡在Building gradle project infod的最快速解决方案
    jdbc.properties各种数据库连接配置
    EL表达式语言总结
    Android sdk目录介绍
    chrome的常用快捷键和命令
    Unity Hub for Mac 破解
    MAC下安装配置Tomcat
  • 原文地址:https://www.cnblogs.com/yue36/p/12853644.html
Copyright © 2011-2022 走看看