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

思路:
  • 首先是题意的理解。上课的时候误以为多组数据之间循环…导致怎么想都不对劲,最后想到是每天时间表的循环,“多组数据”
  • 整体上的想法是首先在输入时判断番剧的持续时间,这段时间如果超过B,那么肯定失败,直接输出"NO"即可;之后对于所有番剧的时间,我们挑出来两个番剧之间的空闲时间,判断能否睡觉,如果能那么加入答案集合,否则就必须醒着,并且持续时间为前后两个番剧的时间+中间空闲时间。注意是循环的,即对于最后一个番剧,我们需要处理它以及第一个番剧之间的时间,思路与上述类似。
  • 不能连续活动B小时,因此不能醒着持续24小时(考虑每天循环),因此至少有一个睡眠的时间段。
  • 具体的处理方法:
    • 输入时间段,直接4个%d;
    • 番剧的时间结构体:起始时间;结束时间;持续时间;重载<用于排序(输入不一定有序,按照起始时间排序)。注意持续时间的计算考虑闭区间;
    • 出现跨夜的情况:起始时间大于结束时间;直接将结束时间加上一整天的时间。注意输出顺序没有规定;
    • 时间的输出:将分钟转换成小时+分钟。
    • 注意时间的计算。比如起始为00:00,那么回退1分钟是23:59,因此为了避免出现负数需要加上1440再取模。
错误记录:
  • 输出“No”而不是“NO”!注意大小写问题
  • bool变量初始化问题。应当是每组数据的开始初始化为true。
  • 注意最后一个番剧和第一个番剧之间的空闲部分如果没达到A,那么醒着的时间的计算是从最后一个番剧的开始到第一个睡眠时间段的开始。
实现:
#include
#include
#include
#include
#include
#include
using namespace std;

int A,B,N;
struct node
{
	int s,e;
	int last_for;
	bool operator<(node& t){if(s!=t.s)return s<t.s;}
};

vector<node> ans;
vector<node> folk; 

int main()
{
	ios::sync_with_stdio(false);
	int a,b,c,d,tmp1,tmp2,t1,t2;
	node tmp;
	
	while(cin>>A>>B>>N)
	{
		A*=60,B*=60;
		ans.clear(),folk.clear();
		bool flag = true;
		for(int i=0;i<N;++i)
		{	
			scanf("%d:%d-%d:%d",&a,&b,&c,&d);
			tmp1 = a*60+b,tmp2 = c*60+d;
			if(tmp1 > tmp2)tmp2+=1440;
			tmp.s = tmp1,tmp.e = tmp2;
			tmp.last_for = tmp2-tmp1+1;
			if(tmp2 - tmp1 +1 > B)
			{
				cout<<"No"<<endl;
				flag = false;
				break;
			}
			folk.push_back(tmp);
		}
		
		if(!flag)continue;
		
		sort(folk.begin(),folk.end());
		
		node last;
		last.s = folk[0].s,last.e = folk[0].e;
		for(int i=1;i<folk.size();++i)
		{
			if((folk[i].s-last.e-1) >= A)//注意持续时间为开区间
			{
				ans.push_back({last.e+1,folk[i].s-1,0});
				last=folk[i];
			}
			else 
			{
				last.e=folk[i].e;
				if(last.e-last.s+1 > B)//注意为闭区间 
				{
					flag = false;
					cout<<"No"<<endl;
					break;
				}
			} 
		}
		if(!flag)continue;
		
		//处理最后和第一个之间的部分,此时last为最后一个醒着的时间段
		t1 = (last.e+1)%1440;//注意需要取模,从而起始时间变为一天中的时间
		t2 = (folk[0].s-1+1440)%1440;
		if(folk[0].s + 1439 - last.e>=A)	
			ans.push_back({t1,t2}); 
		else if(((ans[0].s+1439)%1440 - last.s +1>B) || ans.size() == 0)
		{
			cout<<"No"<<endl;
			continue;
		}
		
		cout<<"Yes"<<endl<<ans.size()<<endl;
		for(int i=0;i<ans.size();++i)printf("%02d:%02d-   %02d:%02d\n",ans[i].s/60,ans[i].s%60,ans[i].e/60,ans[i].e%60);
	}
	
	return 0;
}

你可能感兴趣的:(程序设计思维与实践)