1026. Table Tennis (30)
来源:互联网 发布:程序员述职报告 编辑:程序博客网 时间:2024/06/17 02:27
1. 原题: https://www.patest.cn/contests/pat-a-practise/1026
2. 思路:
题意:
数据处理题。比较复杂,要仔细读题。
细节点:
1. 每人最多服务2小时,比如要求3小时,但服务2小时就结束。
有一个测试点好像是4或者5,我陷在这里很久。
2. 等待服务的队列中有vip时,vip优先。
优先细则是,若vip用户可选择多个球桌,vip球桌空的话,选择vip球桌小的编号,
即使普通球桌编号更小,也不会选。
3.21点到达不会被服务。
4.服务时间四舍五入,即5.4m为5, 5.5以上为6m
思路:
做之前最好画个模型,很复杂。
可以采用队列+排序的方式处理(简单些)
也可以用map的有序性,不需要排序。
只是输出的是按照服务时间来排的,不如队列简单些。
我用的map,用两个map,同时维护所有人和vip用户。
核心是在vip的分配上。每当vip球桌空,要先检查是否有vip用户。
没有按普通桌对待。有vip用户,无vip桌,按普通用户对待。
数据处理题。比较复杂,要仔细读题。
细节点:
1. 每人最多服务2小时,比如要求3小时,但服务2小时就结束。
有一个测试点好像是4或者5,我陷在这里很久。
2. 等待服务的队列中有vip时,vip优先。
优先细则是,若vip用户可选择多个球桌,vip球桌空的话,选择vip球桌小的编号,
即使普通球桌编号更小,也不会选。
3.21点到达不会被服务。
4.服务时间四舍五入,即5.4m为5, 5.5以上为6m
思路:
做之前最好画个模型,很复杂。
可以采用队列+排序的方式处理(简单些)
也可以用map的有序性,不需要排序。
只是输出的是按照服务时间来排的,不如队列简单些。
我用的map,用两个map,同时维护所有人和vip用户。
核心是在vip的分配上。每当vip球桌空,要先检查是否有vip用户。
没有按普通桌对待。有vip用户,无vip桌,按普通用户对待。
3. 源码(已AC):
#include<iostream>#include<map>#include<vector>#include<algorithm>using namespace std;const int open_time = 28800;//开始服务时间const int close_time = 75600;//结束服务时间struct Table//球桌的结构体{ Table() : start_serve(open_time), tag(0) , amount(0) {}//成员初始化 int start_serve;//表示什么时候空闲,可以服务下一个 int tag;//是否vip桌 int amount;//累加服务人数};struct Member//用户的结构体{ Member(): service_time(0) {} const Member &operator=(const Member &b)//重载=运算符 { arrive_time = b.arrive_time; service_time = b.service_time; duration = b.duration; return *this; } int arrive_time;//到达时间 int service_time;//接受服务时间 int duration;//服务持续时间};int main(){ //freopen("in.txt", "r", stdin); int N; scanf("%d", &N); map<int, Member> ordinary, vip;//分别表示所有用户,vip用户的map, key是用户到达时间 for(int i = 0; i < N; i++)//读入数据 { int h, m, s, d, flag; scanf("%d:%d:%d %d %d", &h, &m, &s, &d, &flag);//数据按秒处理 Member tem; tem.arrive_time = h*3600 + m*60 + s;if(d <= 120)tem.duration = d*60;elsetem.duration = 7200;//超过2小时按两小时 ordinary.insert(make_pair(tem.arrive_time, tem)); if(flag) vip.insert(make_pair(tem.arrive_time, tem));//是vip,同时插入vip容器。 } int K, M; scanf("%d %d", &K, &M); vector<Table> ta(K+1);//为简便,从1开始 for(int i = 0; i < M; i++)//读入球桌的属性 { int id; scanf("%d", &id); ta[id].tag = 1; } multimap<int, Member> result;//存储结果,因为key是服务时间,可能相同,用multimap map<int, Member>::iterator it = ordinary.begin(); while(it != ordinary.end())//代码核心,要细心,很容易出错 { if(it->second.service_time != 0)//表明该用户为vip,已处理过 { it++; continue; }int min_vip = 1<<30;//记录vip球桌的最小可以服务时间int vip_id = 0; int min_time = min_vip;//所有球桌的最小可以服务时间 int min_id = 0; for(int i = 1; i <= K; i++)//分别找出所有球桌和vip球桌的最小时间 { if(ta[i].start_serve < min_time) { min_time = ta[i].start_serve; min_id = i; } if(ta[i].tag && ta[i].start_serve < min_vip) { min_vip = ta[i].start_serve; vip_id = i; } }map<int, Member>::iterator it_v = vip.begin();if(!vip.empty() && ((it_v->first >= min_vip && it_v->first == it->first)//1.表桌多人少|| (min_vip <= min_time && it_v->first < min_vip) ) )//2. 多人对一vip桌{//先检查队列中是否有vip用户,且存在vip球桌,有两种情况,见上int time_id = it_v->first; if(ta[vip_id].start_serve < time_id)//分配vip桌,更新球桌和用户的状态 ordinary[time_id].service_time = time_id; else ordinary[time_id].service_time = ta[vip_id].start_serve; ta[vip_id].start_serve = ordinary[time_id].service_time + it_v->second.duration; if(ordinary[time_id].service_time < close_time) ta[vip_id].amount++; Member tem = ordinary[time_id];//插入结果map result.insert(make_pair(ordinary[time_id].service_time, tem)); vip.erase(it_v);//删除vip的记录,也可以不删,用指针。 } else//全部按普通用户对待 { int time_id = it->first; if(ta[min_id].start_serve < time_id) it->second.service_time = time_id; else it->second.service_time = ta[min_id].start_serve; ta[min_id].start_serve = it->second.service_time + it->second.duration; if(it->second.service_time < close_time) ta[min_id].amount++; if(!vip.empty())//此处要判断非空 { if(it_v->first == time_id)//表示该用户是vipvip.erase(it_v); } Member tem = it->second; result.insert(make_pair(it->second.service_time, tem)); it++; } } multimap<int, Member>::iterator mit;//输出结果 for(mit = result.begin(); mit != result.end(); mit++) { int t1 = mit->first; int t2 = mit->second.arrive_time; int wait = int((t1-t2)/60.0 + 0.5);//对分钟四舍五入 if(mit->second.service_time < close_time) { printf("%02d:%02d:%02d ", t2/3600, t2/60%60, t2%60); printf("%02d:%02d:%02d %d\n", t1/3600, t1/60%60, t1%60, wait); } } for(int i = 1; i <= K; i++) { if(i == 1) printf("%d", ta[i].amount); else printf(" %d", ta[i].amount); } printf("\n"); return 0;}
4. 测试用例
参考自:http://blog.csdn.net/jmlikun/article/details/49821845
//正常的检测例子,全部为普通玩家
9
20:52:00 10 0
08:00:00 20 0
08:02:00 30 0
20:51:00 10 0
08:10:29 5 0
08:12:00 10 0
20:50:00 10 0
08:01:30 15 0
20:53:00 10 0
3 1
2
答案为:
08:00:00 08:00:00 0
08:01:30 08:01:30 0
08:02:00 08:02:00 0
08:10:29 08:16:30 6
08:12:00 08:20:00 8
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 table
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 0
答案为:
08:00:00 08:00:00 0
08:01:30 08:01:30 0
08:02:00 08:02:00 0
08:10:00 08:16:30 7
08:12:00 08:20:00 8
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和viptable
9
20:52:00 10 0
07:59:59 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
答案为:
07:59:59 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
//边缘测试例子
1
21:00:00 10 1
3 3
1 2 3
1
20:59:59 10 1
3 3
1 2 3
0
3 1
2
//vip桌子分配例子,有vip桌子时,优先把vip分到编号小的vip桌子,而不是编号小的vip桌子
4
06:00:00 30 1
08:00:00 30 1
10:00:00 30 1
12:00:00 30 1
5 1
3
答案为:
06:00:00 08:00:00 120
08:00:00 08:00:00 0
10:00:00 10:00:00 0
12:00:00 12:00:00 0
1 0 3 0 0
//超过两小时的例子
2
18:00:00 180 1
20:00:00 60 1
1 1
1
答案为:
18:00:00 18:00:00 0
20:00:00 20:00:00 0
2
//关于四舍五入为1分钟的例子,大约等于30秒才+1分钟,小于30则不+
3
07:59:31 60 1
07:59:29 60 1
08:00:30 100 1
2 1
1
答案为:
1
07:59:29 08:00:00 1
07:59:31 08:00:00 0
08:00:30 09:00:00 60
2 1
*/
9
20:52:00 10 0
08:00:00 20 0
08:02:00 30 0
20:51:00 10 0
08:10:29 5 0
08:12:00 10 0
20:50:00 10 0
08:01:30 15 0
20:53:00 10 0
3 1
2
答案为:
08:00:00 08:00:00 0
08:01:30 08:01:30 0
08:02:00 08:02:00 0
08:10:29 08:16:30 6
08:12:00 08:20:00 8
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 table
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 0
答案为:
08:00:00 08:00:00 0
08:01:30 08:01:30 0
08:02:00 08:02:00 0
08:10:00 08:16:30 7
08:12:00 08:20:00 8
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和viptable
9
20:52:00 10 0
07:59:59 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
答案为:
07:59:59 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
//边缘测试例子
1
21:00:00 10 1
3 3
1 2 3
1
20:59:59 10 1
3 3
1 2 3
0
3 1
2
//vip桌子分配例子,有vip桌子时,优先把vip分到编号小的vip桌子,而不是编号小的vip桌子
4
06:00:00 30 1
08:00:00 30 1
10:00:00 30 1
12:00:00 30 1
5 1
3
答案为:
06:00:00 08:00:00 120
08:00:00 08:00:00 0
10:00:00 10:00:00 0
12:00:00 12:00:00 0
1 0 3 0 0
//超过两小时的例子
2
18:00:00 180 1
20:00:00 60 1
1 1
1
答案为:
18:00:00 18:00:00 0
20:00:00 20:00:00 0
2
//关于四舍五入为1分钟的例子,大约等于30秒才+1分钟,小于30则不+
3
07:59:31 60 1
07:59:29 60 1
08:00:30 100 1
2 1
1
答案为:
1
07:59:29 08:00:00 1
07:59:31 08:00:00 0
08:00:30 09:00:00 60
2 1
*/
0 0
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 1026. Table Tennis (30)
- 荷物送り
- LeetCode之removeDuplicates
- CF 241D Numbers
- onSaveInstanceState
- && || ! and or not xor
- 1026. Table Tennis (30)
- Git本地仓库
- A计划(HDU-2102)
- 基础练习 回形取数
- 全局变量、局部变量、静态变量和实例变量的区别
- Android-JNI HellWord
- 1065.A+B and C (64bit) (20)
- linux screen 配置文件 超好用
- ss终端代理