題目描述
衆所周知,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();
}
}