貓睡覺問題(模擬)

問題描述

衆所周知,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 不太一樣,也可能是對的,它有一個判題程序來判定你的答案(當然,你對你自己的答案肯定也能肉眼判斷)

Sample input

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

Sample output

Yes
1
01:07-22:13
No

解題思路

這個題的思路比較簡單,但是處理起來有些複雜。

思路是先把兩個區間中間相隔的時間小於A的區間合併,這樣剩下的睡覺時間都可以睡A小時(只剩一個區間需要特判一下)。

之後判斷合併完畢的區間持續時間是否超過了B小時,如果超過,那就輸出"No",否則,輸出剩下能睡覺的時間即可。

PS:我的代碼存儲小時和分鐘,中間重載了運算符,所以會比較長,其實可以直接存儲分鐘,就是hour*60+minute,這樣只在最終輸出的時候轉化一下格式,代碼長度會大大減少。

完整代碼

//#pragma GCC optimize(2)
//#pragma G++ optimize(2)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

struct timeNode{//時間節點
    timeNode(int _h=0,int _min=0):h(_h),minute(_min){}
    timeNode operator-(const timeNode& t){
        timeNode tempt(h,minute);
        if(tempt<t){ tempt.h+=24; }
        if(tempt.minute<t.minute){ tempt.h-=1; tempt.minute+=60; }
        tempt.minute-=t.minute; tempt.h-=t.h;
        return tempt;
    }
    bool operator<(const timeNode& t){
        if(h<t.h) return true;
        else if(h>t.h) return false;
        else return minute<t.minute;
    }
    bool operator>(const timeNode& t){
        if(h>t.h) return true;
        else if(h<t.h) return false;
        else return minute>t.minute;
    }
    timeNode& operator=(const timeNode& t){ h=t.h; minute=t.minute; return *this; }
    int h,minute;
};
timeNode& minus1min(timeNode& t){//減去一分鐘
    timeNode tempt=t;
    if(tempt.minute==0){
        if(tempt.h==0) tempt.h+=24;
        tempt.h--; tempt.minute+=60;
    }
    tempt.minute--;
    return tempt;
}
timeNode& plus1min(timeNode& t){//加上一分鐘
    timeNode tempt=t;
    tempt.minute+=1;
    if(tempt.minute==60){
        tempt.minute=0; tempt.h++;
    }
    if(tempt.h==24) tempt.h=0;
    return tempt;
}
struct timeInterval{//時間區間
    timeInterval(){}
    timeInterval(struct timeNode _st,struct timeNode _et){
        startTime=_st; endTime=_et;
    };
    bool operator<(const timeInterval& t){ return startTime<t.startTime; }
    timeInterval& operator=(const timeInterval& t){ startTime=t.startTime; endTime=t.endTime; return *this;}
    timeNode startTime,endTime;
};
timeInterval tiInt[24];
int a,b,n,cnt;
bool comp(timeInterval &_a,timeInterval &_b){
    return _a<_b;
}
int main(){
    while(scanf("%d %d %d",&a,&b,&n)!=EOF){
        timeNode A(a,1),B(b-1,59);//這裏是爲了應對題目中說的閉區間,後面的比較會更加方便
        bool flag=true;cnt=0; 
        for (int i=1; i<=n; i++){
            int a1,a2,a3,a4;
            scanf("%d:%d-%d:%d",&a1,&a2,&a3,&a4);
            timeNode t1(a1,a2),t2(a3,a4);
            tiInt[++cnt].startTime=t1; tiInt[cnt].endTime=t2;
        }
        sort(tiInt+1,tiInt+1+cnt,comp);
        for (int i=1; i<cnt; i++){//最後一個區間不合並
            if(tiInt[i+1].startTime-tiInt[i].endTime<A){//兩個區間之間睡眠時間少於a,區間合併
                tiInt[i].endTime=tiInt[i+1].endTime;
                for (int j=i+1; j<cnt; j++)//向前挪
                    tiInt[j]=tiInt[j+1];
                cnt--; i--;
            }
        }
        if(cnt!=1 && tiInt[1].startTime-tiInt[cnt].endTime<A){
            tiInt[cnt].endTime=tiInt[1].endTime;
            for (int i=1; i<cnt; i++) tiInt[i]=tiInt[i+1];
            cnt--;
        }
//        所有區間合併完畢,剩下的空餘時間都可以用來完整睡覺。

//        輸出合併結果,查看
//        for (int i=1; i<=cnt; i++){//output
//            printf("OUTPUT: %02d:%02d-%02d:%02d\n",tiInt[i].startTime.h,tiInt[i].startTime.minute,tiInt[i].endTime.h,tiInt[i].endTime.minute);
//        }

        for (int i=1; i<=cnt; i++){//判斷連續活動時間會不會超時
            if(tiInt[i].endTime-tiInt[i].startTime>B){
                flag=false; break;
            }
        }
        if(!flag) {
            printf("No\n");continue;
        }
//        特殊情況,合併後還剩一個區間,判斷剩下的時間夠不夠睡覺
        if(cnt==1 && tiInt[1].startTime-tiInt[1].endTime<A){
            printf("No\n");continue;
        }
//        剩下的時間都可以用來睡覺,直接默認睡滿
        printf("Yes\n%d\n",cnt);
        for (int i=1; i<=cnt; i++){
            timeNode t1=plus1min(tiInt[i%cnt==0?cnt:i%cnt].endTime);
            timeNode t2=minus1min(tiInt[(i+1)%cnt==0?cnt:(i+1)%cnt].startTime);
            printf("%02d:%02d-%02d:%02d\n",t1.h,t1.minute,t2.h,t2.minute);
        }
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章