【20200522程序设计思维与实践 Week14 限时大模拟&补题】


猫睡觉问题

题意

众所周知,TT家里有一只魔法喵。这只喵十分嗜睡。一睡就没有白天黑夜。喵喵一天可以睡多次!!每次想睡多久就睡多久╭(╯^╰)╮

喵睡觉的时段是连续的,即一旦喵喵开始睡觉了,就不能被打扰,不然喵会咬人哒[○・`Д´・ ○]

可以假设喵喵必须要睡眠连续不少于 A 个小时,即一旦喵喵开始睡觉了,至少连续 A 个小时内(即A*60分钟内)不能被打扰!

现在你知道喵喵很嗜睡了,它一天的时长都在吃、喝、拉、撒、睡,换句话说要么睡要么醒着滴!

众所周知,这只魔法喵很懒,和TT一样懒,它不能连续活动超过 B 个小时。

猫主子是不用工作不用写代码滴,十分舒适,所以,它是想睡就睡滴。

但是,现在猫主子有一件感兴趣的事,就是上BiliBili网站看的新番。

新番的播放时间它已经贴在床头啦(每天都用同一张时间表哦),这段时间它必须醒着!!

作为一只喵喵,它认为安排时间是很麻烦的事情,现在请你帮它安排睡觉的时间段。


思路

本题初看相比上次的会议安排简单。困难点主要有三:格式读入输出、时间闭区间、循环安排。

读入采用的方法是读取一行字符串,并根据格式取相应索引解析出起止时间信息,存入TIME结构体数组play。显示答案时格式输出时间信息即可。

时间闭区间的处理是容易出错的地方,为此在TIME结构体中重载了特殊的减法,将计算结果与代表A小时和B小时的TIME结构体比较,还提供了p1m()和m1m()两个方法,方便放送时间和睡觉时间互相转换。

时间循环的处理方式如下:首先检查所有放送时间的间隔,如果间隔超过A即可睡觉,将该段时间的最大长度(即前一次放送结束1min到后一次放送开始前1min)加入TIME结构体数组sleep,否则跳过,这就是“最有可能满足要求”的安排。接着检查这一睡觉安排是否可行:检查每两个睡时间隔是否超过最大醒时,若全部未超过则该安排可行。这样的处理方式下,只需要在扫描过程中判断一次数组首尾元素关系即可环形判断。


Debug

本题第一个费时的调试点在闭区间的时间段处理上。因为将小时和分钟分开记录,进位和取模的细节较为繁琐,还会出现24:00和00:-1之类的显示。

第二个排查出的bug为对安排可行的判断。有一种情况是第一次处理完后,没有可睡觉的时间段,这时在接下来的处理中是排查不出安排不可行的。添加了对这种情况的判断。

但就是这种情况的一个小细节导致了大量浪费时间的查错:此处的输出没有和一开始一样注意到文本的大小写。


代码

#include<iostream>
#include<string>
#include<algorithm>
#include<iomanip>
using namespace std;

struct TIME{
    int hh;
    int mm;
    int type;//0��ʼ��1���� 

	void p1m(){
		mm++;
		if(mm>=60){
			mm-=60;
			hh++;
		} 
		if(hh>=24){
			hh-=24;
		}
	}

	void m1m(){
		mm--;
		if(mm<=-1){
			mm+=60;
			hh--;
		}
		if(hh<=-1){
			hh+=24;
		} 
	}

    void operator=(TIME& t){
        hh=t.hh;
        mm=t.mm;
        type=t.type; 
    }

    bool operator<(const TIME& t)const{
        if(hh!=t.hh)return hh<t.hh;
        return mm<t.mm;
    }
    bool operator>(const TIME& t)const{return t<*this;}
    bool operator>=(const TIME& t)const{return !(*this<t);}
    bool operator<=(const TIME& t)const{return !(t<*this);}
    bool operator==(const TIME& t)const{return !(*this<t)&&!(t<*this);}
    bool operator!=(const TIME& t)const{return (*this<t)||(t<*this);}
	
	TIME operator-(TIME& t){
		TIME temp;
		temp=*this;
		
		if(temp.mm<t.mm){
			temp.mm+=60;
			temp.hh--;
		}
		temp.mm-=t.mm;
		if(temp.hh<t.hh)temp.hh+=24;
		temp.hh-=t.hh;
		
		if(temp.hh==0&&temp.mm==0){
			temp.mm=-2;
			return temp;
		}
		if(temp.hh==0&&temp.mm==1){
			temp.mm=-1;
			return temp;
		}
		
		if(temp.mm<2){
			temp.mm+=60;
			temp.hh--;
		}
		temp.mm-=2; 
		return temp;
	}
	
    void setHour(int x){
        mm=59;
        hh=x-1;
    }
};

void deal(string str,TIME& a,TIME& b){
    int h,m;

    h=str[0]-'0';
    h*=10;
    h+=(str[1]-'0');
    a.hh=h;

    m=str[3]-'0';
    m*=10;
    m+=(str[4]-'0');
    a.mm=m;
    
    a.type=0;

    h=str[6]-'0';
    h*=10;
    h+=(str[7]-'0');
    b.hh=h;

    m=str[9]-'0';
    m*=10;
    m+=(str[10]-'0');
    b.mm=m;
    
    b.type=1;
}

void output(TIME A,TIME B){
    cout<<setw(2)<<setfill('0')<<A.hh<<":";
    cout<<setw(2)<<setfill('0')<<A.mm<<"-";
    cout<<setw(2)<<setfill('0')<<B.hh<<":";
    cout<<setw(2)<<setfill('0')<<B.mm<<endl;
}

int A,B,N;

int pSZ,sSZ;
TIME play[50];
TIME sleep[50];
string playTIME;
TIME tempA,tempB;
TIME Ahour,Bhour;

int main(){
    while(cin>>A>>B>>N){
        pSZ=sSZ=0;
        Ahour.setHour(A);
        Bhour.setHour(B);
        for(int i=1;i<=N;i++){
            cin>>playTIME;
            deal(playTIME,tempA,tempB);
            play[++pSZ]=tempA;
            play[++pSZ]=tempB;
        }
        sort(play+1,play+pSZ+1);

        if(play[1].type==1){
            for(int i=1;i<pSZ;i+=2){
                if(play[i+1]-play[i]>=Ahour){
                    play[i].p1m();
					sleep[++sSZ]=play[i];
                    sleep[sSZ].type=0;
                    play[i+1].m1m();
                    sleep[++sSZ]=play[i+1];
                    sleep[sSZ].type=1;
                }
            }
        }else{
            for(int i=2;i<pSZ-1;i+=2){
                if(play[i+1]-play[i]>=Ahour){
					play[i].p1m();
                    sleep[++sSZ]=play[i];
                    sleep[sSZ].type=0;
                    play[i+1].m1m();
                    sleep[++sSZ]=play[i+1];
                    sleep[sSZ].type=1;
                }
            }
            if(play[1]-play[pSZ]>=Ahour){
                play[pSZ].p1m();
				sleep[++sSZ]=play[pSZ];
                sleep[sSZ].type=0;
                play[1].m1m();
                sleep[++sSZ]=play[1];
                sleep[sSZ].type=1;
            }
        }
 
        if(sSZ==0){
        	cout<<"No"<<endl;//��Сд��mmml�� 
        	continue;
		}
        
		int jdg=0;
        for(int i=2;i<sSZ;i+=2){
            if(sleep[i+1]-sleep[i]>Bhour){
                jdg=1;
                break;
            }
        }
        if(sleep[1]-sleep[sSZ]>Bhour)jdg=1;
        if(jdg)cout<<"No"<<endl;
        else{
            cout<<"Yes"<<endl<<sSZ/2<<endl;
            for(int i=1;i<sSZ;i+=2){
                output(sleep[i],sleep[i+1]);
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值