Week 14 模擬 A - 貓睡覺問題

題目描述

衆所周知,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();
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章