WEEK14 限时测试 A - 猫睡觉问题

A - 猫睡觉问题

题目描述

众所周知,TT家里有一只魔法喵。这只喵十分嗜睡。一睡就没有白天黑夜。喵喵一天可以睡多次!!每次想睡多久就睡多久╭(╯^╰)╮
喵睡觉的时段是连续的,即一旦喵喵开始睡觉了,就不能被打扰,不然喵会咬人哒[○・`Д´・ ○]
可以假设喵喵必须要睡眠连续不少于 A 个小时,即一旦喵喵开始睡觉了,至少连续 A 个小时内(即A*60分钟内)不能被打扰!
现在你知道喵喵很嗜睡了,它一天的时长都在吃、喝、拉、撒、睡,换句话说要么睡要么醒着滴!
众所周知,这只魔法喵很懒,和TT一样懒,它不能连续活动超过 B 个小时。
猫主子是不用工作不用写代码滴,十分舒适,所以,它是想睡就睡滴。
但是,现在猫主子有一件感兴趣的事,就是上BiliBili网站看的新番。
新番的播放时间它已经贴在床头啦(每天都用同一张时间表哦),这段时间它必须醒着!!
作为一只喵喵,它认为安排时间是很麻烦的事情,现在请你帮它安排睡觉的时间段。

Input

多组数据,多组数据,多组数据哦,每组数据的格式如下:
第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 分钟。
不保证输入的新番时间表有序。

Output

我们知道,时间管理是一项很难的活,所以你可能没有办法安排的那么好,使得这个时间段满足喵喵的要求,即每次睡必须时间连续且不少于 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 不太一样,也可能是对的,它有一个判题程序来判定你的答案(当然,你对你自己的答案肯定也能肉眼判断)

Sample Input

12 12 1
23:00-01:00
3 4 3
07:00-08:00
11:00-11:09
19:00-19:59

Sample Output

Yes
1
01:07-22:13
No

提示

你尝试给喵喵喂小鱼干,它告诉了你一个秘密:“媌,吧唧吧唧小鱼…吧唧吧唧干香吧唧吧唧,媌,这题最麻烦吧唧吧唧…的吧唧吧唧是最后一个番到第二天第一个番期间时间段的处理哦,媌,但是吧唧吧唧可以有一种方法可以很容易处理吧唧吧唧吧唧。啊呀,我要去睡觉啦,媌”
(这题最麻烦的是最后一个番到第二天第一个番期间时间段的处理,但是可以有一种方法可以很容易处理)

题解

如果每次运算都进行小时和分钟的进位换算会很麻烦,所以我们把涉及到的所有时间都用分钟表示,只在输入输出时换算成用来表示的时间(如00:00——0、00:59——59、01:00——60、01:30——90、23:59——1439、第二天的00:00——1500)。最短睡觉时间a和最长活动时间b也乘60换算成分钟。
因为睡觉时间不小于A个小时(但可以无限长),活动时间不大于B个小时(但可以无限短),所以就让这个喵能睡就睡(在合适的睡觉时间时,上一个番结束后的下一分钟就睡,下一个番开始前的前一分钟才醒)。
用结构体time来表示一个时间段,包括开始时间st和结束时间ed。time型数组in和sleep用来记录番的时间和睡觉的时间。
输入时,将所有时间段都转化成以分钟计时的。有可能一天中的最后一个番是跨凌晨的,结束时间就会比开始时间的数字还小,这是我们就把结束时间加上24*60。同时在输入时检查若一个番的总时间大于b,则喵就不可能有时间来看这个番,将记录能否成功安排时间的变量suc改为0。
将所有的时间段排序后,从一天中第一个番开始检查。检查时,定义一个time型结构体last,用来记录目前的活动时间的开始时间和结束时间。将目前活动时间last初始化为第一个番的时间。然后循环检查每个番,若活动时间last的结束时间与下一个番的开始时间之差大于a,则说明这段时间可以用来睡觉。否则,喵就必须从last的开始醒着到下一个番的结束,令last的结束时间等于下一个番的结束时间。这时检查last是否长于b,长于b则说明喵无法安排好时间,令suc=0。
检查suc的值,等于0则输出No,并continue。
将所有的番都循环完后,还要检查最后一个番到第一个番之间的时间段。若最后一个番的结束时间到下一天第一个番的开始时间长于a,就可以睡觉。不可以睡觉时,就检查上一天最后一个活动时间last的开始到第二天第一个睡觉时间的开始,时间段是否大于b,大于b则说明无法安排好时间,输出No,并continue。若上两个if都不符合,说明喵可以从最后一个活动时间的开始醒着直到第二天第一个睡觉时间的开始。
还要检查特殊情况,用来睡觉的时间段是否等于0,是则输出No,并continue。
最后,输出Yes,并输出所有睡觉时间段,注意转化成xx:xx的格式。
这题到最后修改时间最长的问题竟然是Yes写成了YES,No写成了NO。一定一定要仔细看题。

代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a,b,n;//睡眠不小于A个小时,活动不大于B个小时
int tot;
struct time{//时间段
	int st,ed;
	bool operator<(const time & t){
		if(st!=t.st)return st<t.st;
	}
};
time in[50];//每个番的开始时间和结束时间
time sleep[50];//每次睡觉的开始时间和结束时间
void print(int t){
	int h=t/60;
	if(h<10){printf("0");}
	printf("%d",h);
	printf(":");
	int m=t%60;
	if(m<10){printf("0");}
	printf("%d",m);
}
int main(){
	while(scanf("%d%d%d",&a,&b,&n)!=EOF){
		a=a*60;b=b*60;
		memset(in,0,sizeof(in));
		memset(sleep,0,sizeof(sleep));
		bool suc=1;
		tot=0;
		for(int i=0;i<n;i++){
			char s[20];//00:00-00:00
			scanf("%s",s);
			int h,m;
			//cout<<s[3]-'0'<<" "<<s[4]-'0'<<endl;
			h=(s[0]-'0')*10+s[1]-'0';
			m=(s[3]-'0')*10+s[4]-'0';
			//cout<<"st["<<i<<"]:"<<h<<" "<<m<<endl;
			in[i].st=h*60+m;
			h=(s[6]-'0')*10+s[7]-'0';
			m=(s[9]-'0')*10+s[10]-'0';
			//cout<<"ed["<<i<<"]:"<<h<<" "<<m<<endl;
			in[i].ed=h*60+m;
			if(in[i].ed<in[i].st){in[i].ed+=24*60;}
			if(in[i].ed-in[i].st>b){
				suc=0;
			}
		}
		sort(in,in+n);

		time last;
		last.st=in[0].st;last.ed=in[0].ed;
		for(int i=1;i<n;i++){
			int brea=in[i].st-last.ed-1;
			if(brea>=a){//空闲时间>=a,可以睡觉
				sleep[tot].st=last.ed+1;
				sleep[tot].ed=in[i].st-1;
				last=in[i];
				tot++;
			}else{//
				last.ed=in[i].ed;
				if(last.ed-last.st+1>b){
					suc=0;break;
				}
			}
		}
		if(suc==0){printf("No\n");continue;}

		if(in[0].st+24*60-last.ed-1>=a){
			sleep[tot].st=(last.ed+1)%(24*60);
			sleep[tot].ed=(in[0].st+24*60-1)%(24*60);
			tot++;
		}else if((sleep[0].st-1+60*24)%(60*24)-last.st+1>b){ //不可以休息 
			printf("No\n");
			continue;
		}
		if(tot==0){ //不可以休息 
			printf("No\n");
			continue;
		}
		printf("Yes\n%d\n",tot);
		for(int i=0;i<tot;i++){
			//print(sleep[i].st);
			print(sleep[i].st);
			printf("-");

			print(sleep[i].ed);
			printf("\n");
		}
		/*if(st[1]<a&&ed[1]+1>b){printf("NO\n");continue;}
		bool suc=1;
		for(int i=1;i<=n;i++){
			if(ed[i]-st[i]+1>b||
				st[i]-ed[i-1]-1<a
				||st[i]-st[i-1]<a+b){
				suc=0;
			}
		}
		if(suc==0){printf("NO\n");continue;}*/
	}	
	return 0;
}
/*你尝试给喵喵喂小鱼干,它告诉了你一个秘密:
“媌,小鱼…干香,媌,这题最麻烦…的
是最后一个番到第二天第一个番期间时间段的处理哦,
媌,但是可以有一种方法可以很容易处理。
啊呀,我要去睡觉啦,媌”*/
/*
printf("Please input a reply:");
char m[100];
scanf("%s",m);
int len=strlen(m);
sprintf(buffer,m,len);*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值