Week14 限时大模拟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 不太一样,也可能是对的,它有一个判题程序来判定你的答案(当然,你对你自己的答案肯定也能肉眼判断)

样例:

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

output:
Yes
1
01:07-22:13
No

思路:

首先一定要弄懂题意,一定要弄懂。(发现最近写的题,不少题都错误的理解成了另外一个意思。)读入A,B。不能连续醒着超过B小时,睡觉的时候至少睡A。则我们在这里取睡觉的最大数,即能睡就睡。然后题意处理,一张时间表是一组数据一直用的,为了时间计算方便,可将其全部转化为以分钟为单位的。构造一个结构体,其中记录每个番的开始时间和结束时间。其中,注意,若结束时间比开始时间小,则证明这个番跨夜了。在此可将结束时间加上60*24。在读入数据的时间,若一个番的时间大于能醒着的最大时间,则直接判断不能。然后将所有读入的时间按照开始时间排序,因为本题中不会出现交叉的。然后从第一个番开始,记录下从什么时候醒着的,以用来判断是否能继续看番,记录上一个番的结束时间,用来判读是否能睡觉。再每次遍历到下一个番的时候,计算这个番开始时间,和上一个番的结束时间之间能不能睡觉,如果可以的话,则记录下这个休息的时间,并将这个番的时间记录下来,即开始时间和结束时间。如果不可以睡觉,则判断是否能继续看,即从上一次醒来到这个番的结束,这段时间是否比能醒的最大时间大,如果是,则不能成功。否则只记录下结束时间,因为开始时间没有变。其中要对最后一个番进行单独处理,因为这个番的时间可以看为循环数组,最后一个番的时间会影响到明天的时间。在此判断在这最后一个番结束后和明天的第一个番的开始时间之间能不能睡觉,能得话没记录下来。否则判断上一个开始时间到当前记录得第一个能休息的时间之间的时间大小,如果大于B,则失败。最后将记录下来的休息时间全部输出即可。

代码:

#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;

struct T{
	int S;  //开始时间, 
	int E;   //结束时间 
	bool operator <(const T &t)const{
		if(S!=t.S) return S<t.S;
	}
};
T Time[100];
T ans[100];
int tot;
int A,B,N;

void f(int t){
	int t1=t/60;
	if(t1<10) cout<<0;
	cout<<t1;
	cout<<":";
	
	int t2=t%60;
	if(t2<10) cout<<0;
	cout<<t2;
}
int main(){

	int a,b;
	char c;
	while(cin>>A>>B>>N){  //A至少休息的时间  B最多睁眼的时间 
		A*=60, B*=60; 
		tot=0;
		int ret=1;  //可以 
		memset(Time,0,sizeof(Time));
		memset(ans,0,sizeof(ans));
		for(int i=0; i<N;i++){
			cin>>a>>c>>b;
			Time[i].S=a*60+b;
			cin>>c;
			cin>>a>>c>>b;
			Time[i].E=a*60+b;
			if(Time[i].S>Time[i].E) Time[i].E+=24*60; 
			if(Time[i].E-Time[i].S>B){
				ret=0;
				break;
			}
		}
		sort(Time,Time+N);
		
		T last;
		last.S=Time[0].S, last.E=Time[0].E;
				
		for(int i=1;i<N;i++){
			int tmp=Time[i].S-last.E-1;
			if(tmp>=A){   //可以睡觉 
				ans[tot].S=last.E+1;
				ans[tot].E=Time[i].S-1;
				last=Time[i]; 
				tot++;
			}else{//不可以睡觉 
				last.E=Time[i].E;
				if(last.E-last.S+1>B){ //时间超过 
					ret=0;
					break;
				} 			
			}
		}	
		if(!ret){
			cout<<"No"<<endl;
			continue; 
		} 
			//检查交界处 
		if(Time[0].S+24*60-last.E-1>=A){ //可以睡觉 
			ans[tot].S=(last.E+1)%(60*24);
			ans[tot].E=(Time[0].S+60*24-1)%(60*24); //防止是负数 
			tot++; 
		}else if(tot==0||(ans[0].S-1+60*24)%(60*24)-last.S+1>B){ //不可以休息 
			cout<<"No"<<endl;
			continue;
		}
		
	
		cout<<"Yes"<<endl;
				cout<<tot<<endl; 
		for(int i=0;i<tot;i++){
			f(ans[i].S);
			cout<<"-";
			f(ans[i].E);
			cout<<endl;
		}
		
	}
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值