题目描述
众所周知,TT家里有一只魔法喵。这只喵十分嗜睡。一睡就没有白天黑夜。喵喵一天可以睡多次!!每次想睡多久就睡多久╭(╯^╰)╮
喵睡觉的时段是连续的,即一旦喵喵开始睡觉了,就不能被打扰,不然喵会咬人哒[○・`Д´・ ○]
可以假设喵喵必须要睡眠连续不少于 A 个小时,即一旦喵喵开始睡觉了,至少连续 A 个小时内(即A*60分钟内)不能被打扰!
现在你知道喵喵很嗜睡了,它一天的时长都在吃、喝、拉、撒、睡,换句话说要么睡要么醒着滴!
众所周知,这只魔法喵很懒,和TT一样懒,它不能连续活动超过 B 个小时。
猫主子是不用工作不用写代码滴,十分舒适,所以,它是想睡就睡滴。
但是,现在猫主子有一件感兴趣的事,就是上BiliBili网站看的新番。
新番的播放时间它已经贴在床头啦(每天都用同一张时间表哦),这段时间它必须醒着!!
作为一只喵喵,它认为安排时间是很麻烦的事情,现在请你帮它安排睡觉的时间段。
输入
多组数据,多组数据,多组数据哦,每组数据的格式如下:
第1行输入三个整数,A 和 B 和 N (1 <= A <= 24, 1 <= B <= 24, 1 <= n <= 20)
第2到N+1行为每日的新番时间表,每行一个时间段,格式形如 hh:mm-hh:mm (闭区间),这是一种时间格式,hh:mm 的范围为 00:00 到 23:59。注意一下,时间段是保证不重叠的,但是可能出现跨夜的新番,即新番的开始时间点大于结束时间点。
保证每个时间段的开始时间点和结束时间点不一样,即不可能出现类似 08:00-08:00 这种的时间段。时长的计算由于是闭区间所以也是有点坑的,比如 12:00-13:59 的时长就是 120 分钟。
不保证输入的新番时间表有序。
输出
我们知道,时间管理是一项很难的活,所以你可能没有办法安排的那么好,使得这个时间段满足喵喵的要求,即每次睡必须时间连续且不少于 A 小时,每次醒必须时间连续且不大于 B 小时,还要能看完所有的番,所以输出的第一行是 Yes 或者 No,代表是否存在满足猫猫要求的时间管理办法。
然后,对于时间管理,你只要告诉喵喵,它什么时候睡觉即可。
即第2行输出一个整数 k,代表当天有多少个时间段要睡觉
接下来 k 行是喵喵的睡觉时间段,每行一个时间段,格式形如 hh:mm-hh:mm (闭区间),这个在前面也有定义。注意一下,如果喵喵的睡眠时段跨越当天到达了明天,比如从23点50分睡到0点40分,那就输出23:50-00:40,如果从今晚23:50睡到明天早上7:30,那就输出23:50-07:30。
输出要排序吗?(输出打乱是能过的,也就是说,题目对输出的那些时间段间的顺序是没有要求的)
哦对了,喵喵告诉你说,本题是 Special Judge,如果你的输出答案和 Sample 不太一样,也可能是对的,它有一个判题程序来判定你的答案(当然,你对你自己的答案肯定也能肉眼判断)
样例输入
12 12 1
23:00-01:00
3 4 3
07:00-08:00
11:00-11:09
19:00-19:59
样例输出
Yes
1
01:07-22:13
No
思路
综述
对于某一时间段,只有两个状态,醒着或者睡觉;
两个状态满足以下条件:
醒着:不能连续超过B小时
睡觉:必须连续大于等于A小时
将时间看做一段一段的,即醒着或者睡觉,两者交替出现,互为补集;
所有的看番的时间必须是醒着的,看番时间的补集,也即时间段的集合,可以是睡觉时间,对该集合内的时间段做判断,如果满足睡觉的要求,就睡觉,记录所有可以睡觉的时间段,即为集合sp;
求解sp的补集,即为醒着的时间段,对醒着的时间段逐一判断,若都满足醒着的条件,则猫猫可以合理安排时间,否则就不行;
过程
求两次补集,做两次判断即可解决;
Step1:
找出所有看番时间段的补集;
Step2:
对上一步找出的补集,判断能否睡觉,能睡觉的时间作为一个集合;
Step3:
对上一步做出的睡觉时间的集合求补集,即为清醒的时间;
Step4:
对上一步清醒的时间做判断;
总结
备注:代码在写的时候,时间点全部用的看番的时间点,睡觉的时间点也是用的看番的时间点,这时需要注意,因为看番的时间点不是睡觉的时间点,如果某睡觉的时间点是aa:bb–cc:dd,则前一个时间点需要加1分钟,后一个时间点需要减一分钟
我遇到的坑点
1、所有的时间点都不重合;
2、00:00的前一分钟是前一天的23:59;
3、23:59的后一分钟是后一天的00:00
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
//思路是先找出 看番之外的时间段,然后判断是否能够睡觉,能够睡觉就加入数组sp
//然后找出睡觉之外的时间段,判断清醒是否超时
//注:闭区间处理 时间段是使用的输入的看番时间段的时间点
//所以 judge 和 right 函数里面value需要相应处理
//结构体里面 是一个时间段 a1:b1--a2:b2
//排序是按照起始时间排的
struct node{
int a1,a2,b1,b2;
bool operator < (const node &P)const{
if(a1 != P.a1)return a1<P.a1;
return b1<P.b1;
}
};
vector<node> v;
int A,B,N;
vector<node> v2;
vector<node> sp;//要睡觉的时间
//找出所有的睡眠时间
//判断该时间段是否能够 睡觉aa:bb--cc:dd aa:bb--cc:dd
void judge(node nd){
int num = A*60;
int value;
if(nd.a2<nd.a1){
value = (nd.a2+24)*60+nd.b2-nd.a1*60-nd.b1;
}else if(nd.a2==nd.a1 && nd.b2 < nd.b1){
value = (nd.a2+24)*60+nd.b2-nd.a1*60-nd.b1;
}else{
value = nd.a2*60+nd.b2-nd.a1*60-nd.b1;
}
value--;
if(value>=num){
sp.push_back(nd);
}
}
//判断该时间段是否超过Bh
bool right(node nd){
int num = B*60;
int value;
if(nd.a2<nd.a1){
value = (nd.a2+24)*60+nd.b2-nd.a1*60-nd.b1;
}else if(nd.a2==nd.a1 && nd.b2 < nd.b1){
value = (nd.a2+24)*60+nd.b2-nd.a1*60-nd.b1;
}else{
value = nd.a2*60+nd.b2-nd.a1*60-nd.b1;
}
value++;
if(value > num){
return false;
}
return true;
}
void calc(){
v.clear();
node nd;
int st1,ed1;
sort(sp.begin(),sp.end());
//找到所有的清醒的时间---->存在数组v
st1 = sp[0].a2;ed1 = sp[0].b2;
for(int i=1;i<sp.size();i++){
nd.a1=st1;nd.b1=ed1;
nd.a2=sp[i].a1;nd.b2=sp[i].b1;
v.push_back(nd);
st1=sp[i].a2;ed1=sp[i].b2;
}
nd.a1=st1;nd.b1=ed1;
nd.a2=sp[0].a1;nd.b2=sp[0].b1;
v.push_back(nd);
sort(v.begin(),v.end());
for(int i=0;i<v.size();i++){
if(!right(v[i])){
cout<<"No"<<endl;
return;
}
}
if(sp.size()==0){
cout<<"No"<<endl;
return;
}
cout<<"Yes"<<endl;
cout<<sp.size()<<endl;
sort(sp.begin(),sp.end());
for(int i=0;i<sp.size();i++){
// 23:59 24:00 00:00
int num1 = sp[i].a1*60+sp[i].b1;num1++;
num1%=1440;
int num2 = sp[i].a2*60+sp[i].b2;num2--;
if(num2==-1){
num2 = 23*60 + 59;
}
printf("%02d:%02d-%02d:%02d\n",num1/60,num1%60,num2/60,num2%60);
}
return;
}
void work(){
sort(v.begin(),v.end());
//找到所有的除去看番时间之外的时间段
node nd;
int st1,ed1;
st1 = v[0].a2;ed1 = v[0].b2;
// 0 1 2 3 4 5
for(int i=1;i<v.size();i++){
nd.a1=st1;nd.b1=ed1;
nd.a2=v[i].a1;nd.b2=v[i].b1;
v2.push_back(nd);
st1=v[i].a2;ed1=v[i].b2;
}
nd.a1=st1;nd.b1=ed1;
nd.a2=v[0].a1;nd.b2=v[0].b1;
v2.push_back(nd);
//判断是否能够睡觉,加入sp数组
for(int i=0;i<v2.size();i++){
judge(v2[i]);
}
//睡觉时间 不睡觉不行
if(sp.size()==0){
cout<<"No"<<endl;
return;
}
//计算清醒时间是否可行
calc();
}
int main(){
int a1,b1,a2,b2;
while(~scanf("%d%d%d",&A,&B,&N)){
node nd;
v.clear();
sp.clear();
v2.clear();
getchar();
for(int i=0;i<N;i++){
cin>>nd.a1;
getchar();
cin>>nd.b1;
getchar();
cin>>nd.a2;
getchar();
cin>>nd.b2;
getchar();
v.push_back(nd);
}
work();
}
}