众所周知,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
这个题的思路其实非常的简单,就是:能睡的时候就多睡会,睡醒了起来看番,看完了能睡就接着睡。实际上就是按照番剧的开始时间从小到大排序,之后算出番剧之间的时间间隔(排序第一的番剧要与最后的番剧算)。然后在相邻番剧间隔大于最低睡觉时长的时间段安排睡觉,其他时间安排看番或者醒着。同时使用一个变量维护连续醒着的时长,当发现时长超过最大时长时,失败,否则成功。总体来说思路还是比较简单的。但是,难点在于番剧之间的间隔的算法,尤其是第一个番剧和最后一个番剧的时间间隔很麻烦。但是经过简化后,可以发现,番剧之间的间隔分为两类,一类是跨过0点的两番剧间隔,此时需要独立运算,其间隔为两番剧到0点的和,其他的直接运算就可以,即后项的开始时间减去前项的结束时间。如果算出的时间间隔为负数,则使得该数加1440即可(这里画个圆就很容易知道,这个负数是节目长度的绝对值)。最后是开始的位置,这里选择第一个间隔大于最低睡眠时间的番剧开始时间,这样可以保证在看该番剧的时候猫咪一定是刚起的,即连续清醒时间为0。最后按照格式输出即可。
#include
#include
#include
#include
using namespace std;
class times
{
public:
int s[2];
int e[2];
int kuaye;
void ini(string init)
{
s[0]=(init[0]-48)*10+(init[1]-48);
s[1]=(init[3]-48)*10+(init[4]-48);
e[0]=(init[6]-48)*10+(init[7]-48);
e[1]=(init[9]-48)*10+(init[10]-48);
if(s[0]>e[0]) kuaye=1;
else kuaye=0;
}
bool operator <(const times& t) const
{
if(s[0]!=t.s[0]) return s[0]<t.s[0];
else return s[1]<t.s[1];
}
bool operator ==(const times& t) const
{
return (s[0]==t.s[0]&&s[1]==t.s[1]&&e[0]==t.e[0]&&e[1]==t.e[1]);
}
int operator -(const times& t) const
{
if(t<*this||t==*this||t.kuaye==1)
{
int a;
if(s[1]>=t.e[1])
{
a=((s[0]-t.e[0])*60+(s[1]-t.e[1])-1);
}
else a=((s[0]-1-t.e[0])*60+(s[1]+60-t.e[1])-1);
if(a<0) a+=1440;
return a;
}
else
{
return ((23-t.e[0])*60+(60-t.e[1])+(s[0])*60+s[1]-1);
}
}
int change()
{
if(kuaye==0)
{
if(e[1]<s[1])
{
return ((e[0]-1-s[0])*60+(e[1]+60-s[1]+1));
}
else
{
return ((e[0]-s[0])*60+(e[1]-s[1]+1));
}
}
else
{
return ((23-s[0])*60+(60-s[1])+(e[0])*60+(e[1]+1));
}
}
void print()
{
int a,b,c,d;
a=s[0];
b=s[1];
c=e[0];
d=e[1];
if(a<10) printf("0%d",a);
else printf("%d",a);
if(b<10) printf(":0%d-",b);
else printf(":%d-",b);
if(c<10) printf("0%d",c);
else printf("%d",c);
if(d<10) printf(":0%d",d);
else printf(":%d",d);
}
};
int dt[25];
int main()
{
int a,b,k;
while(scanf("%d %d %d",&a,&b,&k)!=EOF)
{
memset(dt,0,sizeof(dt));
bool can=true;
int count=0;
int temp=0;
int start=-1;
string str;
times* table;
times* ans;
table=new times[k];
ans=new times[k];
for(int i=0;i<k;i++)
{
cin>>str;
table[i].ini(str);
}
a=a*60;
b=b*60;
sort(table,table+k);
for(int i=0;i<k;i++)
{
int a=i;
int b=i-1;
if(b<0) b=k-1;
dt[i]=table[a]-table[b];
}
for(int i=0;i<k;i++)
{
if(dt[i]>=a)
{
start=i;
break;
}
}
if(start==-1)
{
printf("No\n");
continue;
}
for(int i=0;i<k;i++)
{
temp+=table[(start+i)%k].change();
if(dt[(start+i+1)%k]<a)
{
temp+=dt[(start+i+1)%k];
}
if(temp>b)
{
can=false;
break;
}
if(dt[(start+i+1)%k]>=a)
{
temp=0;
int a,b,c,d;
a=table[(start+i)%k].e[0];
b=table[(start+i)%k].e[1]+1;
c=table[(start+i+1)%k].s[0];
d=table[(start+i+1)%k].s[1]-1;
if(b==60)
{
b=0;
a=a+1;
if(a==24) a=0;
}
if(d==-1)
{
d=59;
c=c-1;
if(c==-1) c=23;
}
ans[count].s[0]=a;
ans[count].s[1]=b;
ans[count].e[0]=c;
ans[count].e[1]=d;
count++;
}
}
if(can)
{
printf("Yes\n");
printf("%d\n",count);
for(int i=0;i<count;i++)
{
ans[i].print();
printf("\n");
}
}
else printf("No\n");
}
return 0;
}
非常难的一道题,需要考虑的细节有些多,虽然思路上来说并不困难。这里尤其是要注意能否考虑到疲劳累积的问题,即需要选择一个猫咪必然的刚醒的点为起始,否则,不能保证轮询一圈下来之后最终状态和初始状态相同。另外就是,第一个番剧和最后的番剧的处理真的很难,需要考虑很久才可以找到规律。总之,挺难的一道题目,做出来真的非常有成就感,虽然时间过长了。。。