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

思路

本题主要考察对题目的理解和细心程度,没有使用算法,遍历每个番剧时间长度,判断是否超出最大活动时间,超出了就直接输出No,随后对时间段按开始时间排序,判断每个番剧时间段之间的间隔,如果间隔时间大于等于睡觉的最小时间,我们就让猫睡觉,因为猫活动时间有限,睡觉时间无限,所以尽可能让猫睡觉即可。如果时间不够睡觉,就不能睡觉,活动时间加上这个间隔时间以及下一个番剧的时间,如果超过了活动的最大时间,则退出循环,输出No,不超过则继续遍历,遍历完成之后,还要考虑相邻两天之间的影响,也就是前一天的最后一个番剧到今天的第一个番剧的之间的间隔,也要遍历一次,遍历过程一致,只是在求这个间隔时间的时候需要注意,先判断前一天的最后一个番剧是否跨过0点,跨过0点没事,直接用它的结束时间按减去今天第一个番剧的开始时间即可,没有跨过0点,求出来的值就是负数,而且绝对值是真正间隔时间对24小时的补,所以需要加上24*60,这样才能求出间隔时间,判断是否能休息以及是否超过最大活动时间之后,就能求出所有的睡觉时间了,输出就行。
其次,我们求出的睡觉时间不是正确的睡觉时间,因为本题的时间表示是要过完这一分钟才算数,也就是我们求出的睡觉时间假如是23:00-1:01,真实的睡觉开始时间要在23:00结束时,结束时间要在1:01开始前,所以真实的睡觉时间是23:01-1:00,所以我们在加入睡觉时间数组后要对数组里的值进行修改,开始时间加1分钟,结束时间减1分钟,注意进位的不同!

实验代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct tim {
	int h1, m1, h2, m2, temp;
	bool operator<(const tim& b)const {
		if (h1 == b.h1)return m1 < b.m1;
		return h1 < b.h1;
	}
}tv[100],sle[100];
void maintain(int i) {//由于时间段的关系,每个睡觉时间段的开始时间加一分钟,结束时间减一分钟
	if (sle[i].m1 == 59) {
		if (sle[i].h1 == 23) {
			sle[i].h1 = 0; sle[i].m1 = 0;
		}
		else {
			sle[i].h1++; sle[i].m1 = 0;
		}
	}
	else sle[i].m1++;
	if (sle[i].m2 == 0) {
		if (sle[i].h2 == 0) {
			sle[i].h2 = 23; sle[i].m2 = 59;
		}
		else {
			sle[i].h2--; sle[i].m2 = 59;
		}
	}
	else sle[i].m2--;
}
int main() {
	int A, B, N;
	while (cin >> A >> B >> N) {
		memset(tv, 0, sizeof(tv));
		memset(sle, 0, sizeof(sle));
		bool kexing = true;
		bool flag = false;
		int cnt1 = 0;
		int h1, m1, h2, m2;
		for(int i = 0; i < N; i++) {
			scanf("%d:%d-%d:%d", &h1, &m1, &h2, &m2);
			tv[cnt1].h1 = h1; 
			tv[cnt1].m1 = m1;
			tv[cnt1].h2 = h2; 
			tv[cnt1].m2 = m2;
			if (tv[cnt1].h1 < tv[cnt1].h2 || (tv[cnt1].h1 == tv[cnt1].h2 && tv[cnt1].m1 < tv[cnt1].m2)) //该tv不跨夜
				tv[cnt1].temp = tv[cnt1].h2 * 60 + tv[cnt1].m2 - tv[cnt1].h1 * 60 - tv[cnt1].m1 + 1;
			else {
				flag = true;
                tv[cnt1].temp = (24 - tv[cnt1].h1) * 60 - tv[cnt1].m1 + tv[cnt1].h2 * 60 + tv[cnt1].m2 + 1;
			}	
			if (tv[cnt1].temp > B * 60)kexing = false;
			cnt1++;
		}
		sort(tv, tv + N);
		//for (int i = 0; i < cnt1; i++)cout << tv[i].temp << endl;
		tim pt;
		pt.h1 = tv[0].h1; 
		pt.m1 = tv[0].m1;
		pt.h2 = tv[0].h2; 
		pt.m2 = tv[0].m2;
		pt.temp = tv[0].temp;
		int cnt2 = 0;
		for (int i = 1; i < N; i++) {
			int temp = tv[i].h1 * 60 + tv[i].m1 - tv[i - 1].h2 * 60 - tv[i - 1].m2 - 1;
			if (temp >= A * 60) {
				sle[cnt2].h1 = tv[i - 1].h2;
				sle[cnt2].m1 = tv[i - 1].m2;
				sle[cnt2].h2 = tv[i].h1;
				sle[cnt2].m2 = tv[i].m1;
				pt = tv[i];
				maintain(cnt2);
				cnt2++;
			}
			else {
				pt.h2 = tv[i].h2; 
				pt.m2 = tv[i].m2;
				pt.temp += (temp + tv[i].temp);
				if (pt.temp > B * 60) {
					kexing = false;
					break;
				}
			}
		}
		if (kexing == false) {//不满足题意,直接输出No
			cout << "No" << endl;
			continue;
		}
        //满足提意,开始求两天之间的间隔(第一天的最后一个tv到第二天的第一个tv之间)的睡觉时间
		int temp = tv[0].h1 * 60 + tv[0].m1 - pt.h2 * 60 - pt.m2 - 1;
		if (flag == false) temp += 24 * 60;//不跨夜的话算出来的值是负数
		if (temp >= A * 60) {//可以休息
			sle[cnt2].h1 = tv[cnt1 - 1].h2; 
			sle[cnt2].m1 = tv[cnt1 - 1].m2;
			sle[cnt2].h2 = tv[0].h1; 
			sle[cnt2].m2 = tv[0].m1;
			maintain(cnt2);
			cnt2++;
		}
		else {//不能休息
			pt.temp += (temp + tv[0].temp);
			//cout << pt.h1 << " " << pt.m1 << " " << pt.h2 << " " << pt.m2 << " " << pt.temp << endl;
			if (pt.temp > B * 60 ) {
				kexing = false;
			}
		}
		/*for (int i = 1; i <= cnt2; i++)
			cout << sle[i].h1 << " " << sle[i].m1 << " " << sle[i].h2 << " " << sle[i].m2 << endl;*/
		if (cnt2 == 0 || kexing == false)cout << "No" << endl;
		else {
			cout << "Yes" << endl;
			cout << cnt2 << endl;
			for (int i = 0; i < cnt2; i++) {
				printf("%02d:%02d-%02d:%02d\n", sle[i].h1, sle[i].m1, sle[i].h2, sle[i].m2);
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值