1026. Table Tennis (30)

题目如下:

A table tennis club has N tables available to the public. The tables are numbered from 1 to N. For any pair of players, if there are some tables open when they arrive, they will be assigned to the available table with the smallest number. If all the tables are occupied, they will have to wait in a queue. It is assumed that every pair of players can play for at most 2 hours.

Your job is to count for everyone in queue their waiting time, and for each table the number of players it has served for the day.

One thing that makes this procedure a bit complicated is that the club reserves some tables for their VIP members. When a VIP table is open, the first VIP pair in the queue will have the priviledge to take it. However, if there is no VIP in the queue, the next pair of players can take it. On the other hand, if when it is the turn of a VIP pair, yet no VIP table is available, they can be assigned as any ordinary players.

Input Specification:

Each input file contains one test case. For each case, the first line contains an integer N (<=10000) - the total number of pairs of players. Then N lines follow, each contains 2 times and a VIP tag: HH:MM:SS - the arriving time, P - the playing time in minutes of a pair of players, and tag - which is 1 if they hold a VIP card, or 0 if not. It is guaranteed that the arriving time is between 08:00:00 and 21:00:00 while the club is open. It is assumed that no two customers arrives at the same time. Following the players' info, there are 2 positive integers: K (<=100) - the number of tables, and M (< K) - the number of VIP tables. The last line contains M table numbers.

Output Specification:

For each test case, first print the arriving time, serving time and the waiting time for each pair of players in the format shown by the sample. Then print in a line the number of players served by each table. Notice that the output must be listed in chronological order of the serving time. The waiting time must be rounded up to an integer minute(s). If one cannot get a table before the closing time, their information must NOT be printed.

Sample Input:
9
20:52:00 10 0
08:00:00 20 0
08:02:00 30 0
20:51:00 10 0
08:10:00 5 0
08:12:00 10 1
20:50:00 10 0
08:01:30 15 1
20:53:00 10 1
3 1
2
Sample Output:
08:00:00 08:00:00 0
08:01:30 08:01:30 0
08:02:00 08:02:00 0
08:12:00 08:16:30 5
08:10:00 08:20:00 10
20:50:00 20:50:00 0
20:51:00 20:51:00 0
20:52:00 20:52:00 0
3 3 2



题目要求对乒乓球厅的事件进行模拟。

根据用户到达时间排队,有空桌子则按先到先服务的原则处理,如果队列中有VIP用户并且有VIP桌子空闲,则VIP可以“自成一队”,按照到达顺序直接分配到VIP桌,如果没有VIP桌空闲,则VIP和普通用户同样对待。如果队中没有VIP并且编号最小的恰是VIP桌,普通用户也可以使用VIP桌。

这类题目需要处理桌子的空闲与用户的到达、服务时间之间的关系,需要有一个较好的思路,否则很容易混乱。

一个比较好的思路是为每个桌子设定空闲时间,首先全部初始化为上午8:00,当处理一个人时,首先从桌子列表最前面取到桌子,然后根据自己的到达时间和桌子的空闲时间即可计算出桌子的新空闲时间、用户的等待时间和服务时间(有可能到关门时达不到预期服务时间)。

这道题麻烦在VIP上,如果有VIP用户,他们可以“插队”,要处理这些用户,就会让问题变得复杂,不能简单的取出第一个未服务用户和第一个桌子,而是要考虑有VIP用户和VIP桌子的情况,这里有两种优秀的解法:

①类似归并排序的思想,维护普通用户和VIP用户两个队列。

②仅使用一个队列,先考虑VIP情况,没有VIP被处理则按照正常情况处理,算法来自sunbaigui。

我完整的参考了sunbaigui的解法,他的解法非常巧妙,下面罗列一下关键点:

①对用户排序后从前到后处理,初始化服务开始时间为INF,这样当处理完一个人时,他的服务时间不再是INF,由此判断是否处理完毕,不必另设标志。

②不对桌子排序,而是找到所有桌子中空闲时间最早的,从桌子列表从前到后筛选,这样就保证了按照编号的顺序,十分巧妙。

③根据②中找到的最早空闲时间,找出所有符合的桌子和用户,分别存储一个新的容器,后面就针对这两个新的容器处理。

④分情况讨论,单人单桌、多人单桌、多人多桌,在这三种情况下分别判断是否有VIP被服务。

⑤如果④中没有VIP被服务,则取出新容器中第一个用户和第一个桌子,正常处理。

下面的代码来自sunbaigui,我在他代码的基础上加了些注释,方便理解。

#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<string>
#include<string.h>
#include<stdio.h>using namespace std;typedef struct Node
{int arrive, process, tag;int serve, wait; // serve和wait分别代表服务开始时间和等待时间,将serve初始化为INF,从而区分有没有被服务
}Node;
typedef struct Table
{int tag;int freeTime, num; // 每个桌子记录自己的空闲时间和服务数,全部初始化为上午8:00,这样可以迭代着处理
}Table;
bool CmpArrive(Node a, Node b) // 用于对用户的到达时间升序排序
{return a.arrive < b.arrive;
}
bool CmpServe(Node a, Node b) // 对用户按照时间顺序排列,优先按照服务时间排序,如果服务同时开始(多个空桌),按照到达时间升序
{if(a.serve == b.serve)return a.arrive < b.arrive;else return a.serve < b.serve;
}
#define INF 0x6FFFFFFFvector<Node> user;
vector<Table> table;
void UpdateInfo(int userID, int tableID)
{user[userID].serve = max(user[userID].arrive, table[tableID].freeTime);user[userID].wait = user[userID].serve-user[userID].arrive;table[tableID].num++;table[tableID].freeTime = user[userID].serve+min(user[userID].process, 7200); // 最长服务时间为2小时
}
int main()
{//inputint n;scanf("%d",&n);user.resize(n);for(int i = 0; i < n; ++i){int h, m, s;scanf("%d:%d:%d %d%d",&h,&m,&s,&user[i].process,&user[i].tag);user[i].arrive = h*3600+m*60+s;user[i].process *= 60;user[i].serve = INF; user[i].wait = INF; // 初始化为INF,INF就代表未被处理}int k, m;scanf("%d%d",&k,&m);table.resize(k);for(int i = 0; i < k; ++i)table[i].freeTime = 8*3600, table[i].tag = 0, table[i].num = 0; // 所有桌子从上午8:00开始可用for(int i = 0; i < m; ++i){int c;scanf("%d",&c); c--;table[c].tag = 1;}//processsort(user.begin(), user.end(), CmpArrive); // 按照到达时间升序排列,符合排队规则//visited.assign(n, false);for(int i = 0; i < n; ++i){if(user[i].serve != INF) continue; // server时间初始化为INF,不为INF的已经服务完毕。int minFreeTime = INF;for(int j = 0; j < k; ++j)minFreeTime = min(minFreeTime, table[j].freeTime); // 找出最早空闲的桌子int timePoint = max(user[i].arrive, minFreeTime); // 根据队头用户确定当前最早服务时间点if(timePoint >= 21*3600) break; // 判断是否超过营业时间vector<int> userList;vector<int> tableList;for(int j = i; j < n; ++j) // 根据最早服务时间点找到所有可能被服务的人,是为了处理有VIP优先去VIP桌的情况。if(user[j].serve == INF && user[j].arrive <= timePoint) userList.push_back(j);for(int j = 0; j < k; ++j) // 找出所有在时间点之前空闲的桌子,因为可能用户到达晚,因此会有多个桌子空闲if(table[j].freeTime <= timePoint) tableList.push_back(j);bool flag = false; // 判断是否处理了一个服务// 首先特殊处理VIP,如果没有VIP被处理则处理一个普通用户,每次只处理一个if(userList.size() == 1 && tableList.size() > 1) // 单个用户多个桌子,用户为VIP则去找编号最小的VIP桌{if(user[userList[0]].tag == 1){for(int j = 0; j < tableList.size(); ++j){if(table[tableList[j]].tag == 1){flag = true;UpdateInfo(userList[0], tableList[j]);break;}}}}else if(tableList.size() == 1 && userList.size() > 1) // 多人单桌情况,如果为VIP桌找多人中最先到达的VIP为其服务{if(table[tableList[0]].tag == 1){for(int j = 0; j < userList.size(); ++j){if(user[userList[j]].tag == 1){flag = true;UpdateInfo(userList[j], tableList[0]);break;}}}}else if(tableList.size() > 1 && userList.size() > 1) // 多人多桌情况,先找桌子中的VIP桌,有则找用户中最先到达的VIP{for(int t = 0; t < tableList.size(); ++t){if(table[tableList[t]].tag == 1){for(int u = 0; u < userList.size(); ++u){if(user[userList[u]].tag == 1){flag = true;UpdateInfo(userList[u], tableList[t]);break;}}}}}if(!flag) UpdateInfo(userList[0], tableList[0]); // 如果没有VIP被处理,则按照正常情况处理。--i;}//outputsort(user.begin(), user.end(), CmpServe);for(int i = 0; i < n; ++i){if(user[i].serve >= 21*3600) break;int h1, m1, s1, h2, m2, s2;int t = user[i].arrive;h1 = t/3600; t %= 3600;m1 = t/60; t %= 60;s1 = t;t = user[i].serve;h2 = t/3600; t %= 3600;m2 = t/60; t %= 60;s2 = t;// 注意对等待时间的四舍五入为超过30秒算作一分钟printf("%02d:%02d:%02d %02d:%02d:%02d %d\n", h1, m1, s1, h2, m2, s2, (user[i].wait+30)/60);}for(int i = 0; i < k; ++i){if(i != k-1)printf("%d ",table[i].num);else printf("%d\n",table[i].num);}return 0;
}


转载于:https://www.cnblogs.com/aiwz/p/6154036.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/397595.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java运行时异常中文_JAVA——运行时异常(RuntimeException)

Exception中有一个特殊的子类异常RuntimeException运行时异常。如果在函数内抛出该异常&#xff0c;函数上可以不用声明&#xff0c;编译一样通过。如果在函数上声明了该异常。调用者可以不用进行处理。编译一样通过。之所以不用在函数上声明&#xff0c;是因为不需要让调用者处…

内置函数isinstance和issubclass

1. isinstance&#xff08;obj,class&#xff09; 判断对象obj是不是由class生成的对象。 class Foo:passobjFoo()print(isinstance(obj,Foo))obj是Foo的生成的对象&#xff0c;返回True。如果不是&#xff0c;则返回False。 d{x:1} #ddict({x:1} #)print(type(d) is dict) pri…

JavaOne 2016——首日亮点

今年&#xff0c;为期5天的JavaOne会议中&#xff0c;4个会场的议题都进行了直播&#xff0c;演讲稿也在播出之后一并提供。\\来自Terracotta公司EHCache团队的Henri Tremblay&#xff0c;做了主题为《学习Java 8&#xff1a;Lambda表达式和函数式编程&#xff08;Learn Java 8…

指针数据类型 java_C/C++ 指针的小结——指针与其它数据类型(数组、字符串、函数、结构体)的关系...

一、指针与数组和字符串1、指针与数组当声明数时&#xff0c;编译器在连续的内存空间分配基本地址和足够的储存空间&#xff0c;以容纳数组的所有元素。基本地址是数组第一个元素(索引为0)的存储位置。编译器还把数组名定义为指向第一个元素的常量指针。元素的地址是通过索引和…

Linux tr命令详解

tr是个简单的替换命令&#xff0c;从标准输入中替换、缩减和/或删除字符&#xff0c;并将结果写到标准输出。 tr常见命令参数 用法&#xff1a;tr [选项]... SET1 [SET2] 从标准输入中替换、缩减和/或删除字符&#xff0c;并将结果写到标准输出。-c, -C, --complement …

512M内存编译php出错

make时错误如下 1 virtual memory exhausted: Cannot allocate memory make: *** [ext/fileinfo/libmagic/apprentice.lo] Error 1 内存小造成的&#xff0c;为了成功的话需要加上参数 –disable-fileinfo即可参考链接&#xff1a;https://bugs.php.net/bug.php?id48809 转载于…

Android中插件开发篇总结和概述

刚刚终于写完了插件开发的最后一篇文章&#xff0c;下面就来总结一下&#xff0c;关于Android中插件篇从去年的11月份就开始规划了&#xff0c;主要从三个方面去解读Android中插件开发原理。说白了&#xff0c;插件开发的原理就是&#xff1a;动态加载技术。但是我们在开发插件…

java反射机制 路径_Java 反射机制详解

引言本文主要介绍Java中&#xff0c;有关反射机制、类的加载过程、以及控制反转方面的内容。Java 反射机制Java创建对象的方式有哪些&#xff1a;new、反射、反序列化、克隆class对象获取的方法有哪些&#xff1a;类名.class、getClass、forName、classLoader.loadClass(‘包类…

prop和attr在 jquery的

https://www.cnblogs.com/Showshare/p/different-between-attr-and-prop.html转载于:https://www.cnblogs.com/beimingbingpo/p/9254680.html

java传入数据库生成柱状图_Java读取数据库数据生成柱状图

此案例是用swing显示数据的。须要引入jfreechart相关包。不同版本号可能包不同样。本人用的是此案例在ssi框架下会报错&#xff0c;不用框架就没问题。Java后台逻辑代码&#xff1a;public class BarChart {ChartPanel frame1;public BarChart() {CategoryDataset dataset get…

SVN系列操作(一)

SVN是什么&#xff1f; SVN是Subversion的简称&#xff0c;是一个开放源代码的版本控制系统&#xff0c;常用于软件开发项目中&#xff0c;实现代码、文档等的历史版本保存、共享和权限管理。 进入SVN本地目录&#xff0c;第一步操作就是update。 为什么呢&#xff1f;因为SVN是…

ubuntu-14.04.2-desktop使用方法

一、安装VMware Tools 1. 在VMware Workstation11.1.0下安装Ubuntu镜像&#xff1a;ubuntukylin-14.04.2-desktop-amd64.iso 2. 点击虚拟机菜单栏-安装VMware Tools。 3. 在Ubuntu系统光盘中找到VMwareTools-9.9.2-2496486.tar.gz&#xff0c;右键复制到“桌面”&#xff0c;然…

ubuntu 跟xshell的问题

有2个分析&#xff1a; 1&#xff1a;是windos的防火墙没有关闭 2&#xff1a;是虚拟机没有安装sshd服务器 ubuntu在CLI界面下输入&#xff1a;dpkg -l |grep ssh 因为是我安装过的sshd server 要是没有sshd server 就要输入 安装。 三&#xff1a;要是安装完之后 链接显示说…

java gdal postgresql_使用GDAL/OGR操作Postgresql数据库

&#xfeff;&#xfeff;GDAL(Geospatial Data AbstractionLibrary)是一个在X/MIT许可协议下的开源栅格空间数据转换库。它利用抽象数据模型来表达所支持的各种文件格式。它还有一系列命令行工具来进行数据转换和处理。本文将使用GDAL/OGR库读写Postgresql数据库中的表&#x…

Go语言基础之1--标识符、关键字、变量和常量、数据类型、Go的基本程序结构、Golang的特性...

一、前言 当我们项目较为简单时&#xff0c;我们在src目录下新建一个该项目目录&#xff0c;里面存放源码文件即可&#xff0c;见下图&#xff1a; 当我们一个项目较为复杂时&#xff0c;我们可以在src目录下新建一个该项目目录&#xff0c;在针对该项目不同模块创建不同目录&a…

java参数转换匹配规律_隐式转换规则

隐式转换在如下三种不同的情况会被考虑&#xff1a;1、当对象A调用某个方法时&#xff0c;这个方法不存在例如在前一节介绍的1 to 10。会将Int转换为RichInt&#xff0c;然后再调用to方法。在这种情况下&#xff0c;会将对象A(方法的调用者)隐式转换为另一个对象。2、当对象A调…

Semantic-UI的React实现(二):CSS类构造模块

更简单的类名标签 Semantic-UI使用了更简单的类名声明。用过Bootstrap的同学都会被其复杂的类名标签折磨过&#xff0c;例如一个简单的按键样式&#xff0c;不论颜色或是大小&#xff0c;都需要btn-前缀声明&#xff1a; <button type"button" class"btn btn…

T-SQL LIKE子句 模糊查询

MS SQL Server LIKE子句用于使用通配符运算符将值与类似值进行比较。 有两个通配符与LIKE运算符结合使用: 百分号&#xff08;&#xff05;&#xff09;下划线&#xff08;_&#xff09;百分号表示零个&#xff0c;一个或多个字符。 下划线表示单个数字或字符。 符号可以组合使…

ext springmvc mysql_基于ExtJs6前台,SpringMVC-Spring-Mybatis,resteasy,mysql无限极表设计,实现树状展示数据(treepanel)...

先从后台讲起1.表的设计2.mysql查询很容易&#xff0c;关键是要把id,text,parentId查出来/p>"http://mybatis.org/dtd/mybatis-3-mapper.dtd">SELECTbp.id,bb.name brandName,bp.name text,bp.photo_url photoUrl,bp.number,bp.add_time addTime,bp.modify_tim…

C# 之 Int16 Int32 Int64 的区别

Int16 值类型表示值介于 -32768 到 32767 之间的有符号整数。 Int32 值类型表示值介于 -2,147,483,648 到 2,147,483,647 之间的有符号整数。 Int64 值类型表示值介于 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 之间的整数。 --------------------------------…