week14-限时大模拟
问题描述
众所周知,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 不太一样,也可能是对的,它有一个判题程序来判定你的答案(当然,你对你自己的答案肯定也能肉眼判断)
Example
Input
12 12 1
23:00-01:00
3 4 3
07:00-08:00
11:00-11:09
19:00-19:59
1
2
3
4
5
6
Output
Yes
1
01:07-22:13
No
解题方法
解题
首先分析题目,由于是每天执行这个时间表,所以说必须进行休息,不然持续活动时间一定会超出致死量。
最为稳妥的方法是只要可以睡觉的时间就睡觉。
读入各个时间段后按先后顺序进行排序。
首先在一天的第一个活动时间开始之前,可能已经活动了一端时间,因此要先求出这一段时间。通过对所有的活动时间段进行从后向前遍历可以求的已经活动的时间,记为tmp。
然后从前向后遍历所有的时间端,并且维持tmp(已活动时间),在所有足够休息的时间段内进行休息,并将 tmp 置0。将可以休息的时间段记录下来,注意时间区间的开闭。
输入与输出
另一些比较重要的知识是对有固定格式的输入与输出的处理,例如本题中的时间信息。开始我才用的读入方式很蠢,经过查询资料以及助教的提醒,使用了
scanf("%02d:%02d-%02d:%02d", &h1, &m1, &h2, &m2);
这种比较方便的方法进行输入与输出处理。
此外还有很多scanf()的格式控制,留待以后补充。
//scanf()格式控制
代码1(AC)
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
struct node
{
int st, ed, t;
bool operator<(node &b)
{
return st < b.st;
}
void output()
{
int hour1 = (st / 60) % 24;
int minute1 = (st + 60) % 60;
int hour2 = ed >= 0 ? (ed / 60) % 24 : 23;
int minute2 = (ed + 60) % 60;
printf("%02d:%02d-%02d:%02d\n", hour1, minute1, hour2, minute2);
}
};
node x[25], ans[25];
int a, b, n;
void doo()
{
int h1, m1, h2, m2, lt, tt, tmp;
lt = 0;
for (int i = 0; i < n; i++)
{
scanf("%02d:%02d-%02d:%02d", &h1, &m1, &h2, &m2);
x[i].st = h1 * 60 + m1;
x[i].ed = h2 * 60 + m2;
if (x[i].ed < x[i].st)
x[i].ed += 1440;
x[i].t = x[i].ed - x[i].st + 1;
lt = max(lt, x[i].t);
}
if (lt > b * 60)
{
cout << "No" << endl;
return;
}
sort(x, x + n);
if (n == 1)
{
tt = 1440 - x[0].t;
if (tt >= a * 60)
{
cout << "Yes" << endl;
cout << "1" << endl;
int h_1 = ((x[0].ed + 1) / 60) % 24;
int m_1 = (x[0].ed + 1) % 60;
int h_2 = x[0].st - 1 >= 0 ? ((x[0].st - 1) / 60) % 24 : 23;
int m_2 = ((x[0].st - 1) + 60) % 60;
printf("%02d:%02d-%02d:%02d\n", h_1, m_1, h_2, m_2);
}
else
cout << "No" << endl;
return;
}
tt = x[0].st + 1440 - x[n - 1].ed - 1;
if (tt >= a * 60)
tmp = 0;
else
{
tmp = tt + x[n - 1].t;
int p = n - 1;
while (p >= 1 && x[p].st - x[p - 1].ed - 1 < a * 60)
{
tmp += x[p].st - x[p - 1].ed - 1 + x[p - 1].t;
p--;
}
}
//寻找在一天第一个任务开始前使用的时间
int cnt = 0;
for (int i = 0; i < n; i++)
{
tmp += x[i].t;
if (tmp > b * 60)
{
cout << "No" << endl;
return;
}
if (i != n - 1)
{
if (x[i + 1].st - x[i].ed - 1 >= a * 60)
{
ans[++cnt].st = x[i].ed + 1;
ans[cnt].ed = x[i + 1].st - 1;
tmp = 0;
}
else
tmp += x[i + 1].st - 1 - x[i].ed;
if (tmp > b * 60)
{
cout << "No" << endl;
return;
}
}
}
if (tt >= a * 60)
{
cnt++;
ans[cnt].st = x[n - 1].ed + 1;
ans[cnt].ed = x[0].st - 1;
}
if (cnt)
{
cout << "Yes" << endl;
cout << cnt << endl;
for (int i = 1; i <= cnt; i++)
ans[i].output();
}
else
cout << "No" << endl;
}
int main()
{
while (cin >> a >> b >> n)
doo();
}
代码2(wa)
#include <iostream>
using namespace std;
struct node
{
int h, m;
int operator-(const node &c)
{
int ci = h;
if (h < c.h)
{
ci += 24;
}
return ((ci - c.h) * 60 + (m - c.m) + 1);
}
node operator+(int k)
{
node ans;
ans = *this;
ans.m += k;
if (ans.m >= 60)
{
ans.h = (ans.h + 1) % 24;
ans.m = ans.m % 60;
}
if (ans.m < 0)
{
ans.m += 60;
ans.h = (ans.h + 23) % 24;
}
return ans;
}
void output()
{
if (h < 10)
cout << 0;
cout << h << ":";
if (m < 10)
cout << 0;
cout << m;
}
};
node x[50], y[50], z[50];
int a, b, n, cnt;
void doo()
{
a *= 60; //睡眠时间
b *= 60; //
int h_, m_;
char c_;
cnt = 0;
for (int i = 0; i < n; i++)
{
cin >> h_ >> c_ >> m_;
x[cnt].h = h_;
x[cnt].m = m_;
cnt++;
cin >> c_;
cin >> h_ >> c_ >> m_;
x[cnt].h = h_;
x[cnt].m = m_;
cnt++;
}
for (int i = 0; i < 2 * n; i = i + 2)
{
int tit = x[i + 1] - x[i];
if (tit > b)
{
cout << "No" << endl;
return;
}
}
//找到一段足够睡觉的时间
int tt = x[0] - x[cnt - 1] - 2;
int sta = 0;
if (tt >= a)
{
sta = cnt - 1;
}
else
{
for (int i = 2; i < cnt - 1; i = i + 2)
{
tt = x[i] - x[i - 1] - 2;
if (tt >= a)
{
sta = i - 1;
break;
}
}
}
if (tt <= a)
{
cout << "No" << endl;
return;
}
//cout << sta << endl;
int cnt2 = 0;
for (int i = sta + 1; i < cnt; i++)
{
y[cnt2] = x[i];
cnt2++;
}
for (int i = 0; i < sta + 1; i++)
{
y[cnt2] = x[i];
cnt2++;
}
// for (int i = 0; i < cnt2; i++)
// {
// cout << y[i].h << " " << y[i].m << endl;
// }
z[0] = x[sta] + 1;
z[1] = x[(sta + 1) % (2 * n)] + (-1);
// cout << z[0].h << " " << z[0].m << endl;
// cout << z[1].h << " " << z[1].m << endl;
cnt = 2;
node ct = y[0];
// ct.output();
// cout << endl;
for (int i = 1; i < (n * 2) - 2; i += 2)
{
tt = y[i + 1] - y[i] - 2;
if (tt >= a)
{
z[cnt] = y[i] + 1;
z[cnt + 1] = y[i + 1] + (-1);
cnt += 2;
ct = y[i + 1];
// ct.output();
// cout << endl;
}
else
{
if (y[i + 1] - ct >= b)
{
cout << "No" << endl;
return;
}
}
}
if (y[n * 2 - 1] - ct >= b)
{
cout << "No" << endl;
return;
}
cout << cnt / 2 << endl;
for (int i = 0; i < cnt; i += 2)
{
z[i].output();
cout << "-";
z[i + 1].output();
cout << endl;
}
}
int main()
{
while (cin >> a >> b >> n)
{
doo();
}
}