原题链接
http://acm.hdu.edu.cn/showproblem.php?pid=3700
题目描述
题目里的坑
1. 时间段全部是闭区间,这意味着睡觉时间的端点和看番时间的端点不能重合,计算时间长度也不能简单的用两个端点相减。
2. 别看样例里边给的时间段都是有序的,题目里没说有序,所以需要排序。
3. 题目中的A和B分别是指连续睡觉或醒着的时间要求,而不是对睡觉或醒着的总时间的要求。
4. 猫不能一直不睡觉(如果一个睡觉时间段也没有,必须输出No)。
5. Yes和No,不是YES和NO。
6. 时间不要出现-1和1440,这两个最后分别要输出23:59和00:00。
基本思路
为了更好的处理时间,需要将所有的时间字符串转化成时间点(int类型, h o u r × 60 + m i n hour \times 60+min hour×60+min)处理。
这个题的难点在于处理那些跨夜的时间段(开始时间点大于结束时间点)。
题目输入给的是一天内的番剧的时间表(最后一部番的结束时间 - 第一部番的开始时间不会超过24h)。我们可以把时间想象成一个环,绕环一周是24h。只要我们从一部番的开始时间
t
0
t0
t0 统计,一直统计
t
0
+
24
×
60
m
i
n
t0+24\times 60min
t0+24×60min 即可。
可以定义一个时间点结构体TimePoint,其中包含时间点t,以及时间点状态st(表示是番的开始时间还是结束时间)。
维护一个TimePoint类型的结构体数组tp,里面包含所有 t 0 t0 t0到 t 0 + 24 × 60 m i n t0+24 \times 60min t0+24×60min的所有番剧的起始时间点和结束时间点(从小到大有序排列)。 t 0 t0 t0可以选取输入时间表中最早播出的番剧的起始时间。如果一部番剧的结束时间小于起始时间,那么结束时间要加上 24 × 60 24\times60 24×60以区分,最后将 t 0 + 24 × 60 t0+24 \times 60 t0+24×60加入tp数组。
假设tp数组中有n+1个时间点,那么这些时间点形成了n个时间段,其中,有些是番剧播出时间段,有些是空闲的时间段。
遍历前n个时间点(也就是遍历前n个时间段,第i个时间段有tp[i]和tp[i+1]组成),并记录可以用来睡觉的时间段,维护连续醒着的时间,从而判断是否存在满足要求的时间安排。
完整代码
#include<iostream>
#include<sstream>
#include<string>
#include<vector>
#include<algorithm>
#include<cstdlib>
using namespace std;
#define T 1440
int transto(const string &ts)
{
int t1, t2;
char tmp;
istringstream iss(ts);
iss>>t1>>tmp>>t2;
return t1*60+t2;
}
string transback(int t)
{
string ts;
stringstream ss;
int t1 = t/60;
int t2 = t%60;
if(t1 < 10) ss<<0; ss<<t1;
ss<<":";
if(t2 < 10) ss<<0; ss<<t2;
ss>>ts;
return ts;
}
struct TimePoint{
int t;
string st;
TimePoint(int t, const string &st)
{
this->t = t;
this->st = st;
}
bool operator <(const TimePoint &tp) const
{
return t < tp.t;
}
};
vector<TimePoint> tp;
vector<string> slpt;
int A, B, N;
int n, dt, b, st, ed, mint; //b:连续活动时间
string tmp;
bool flag;
int main ()
{
while(cin>>A>>B>>N)
{
A *= 60;
B *= 60;
getchar();
tp.clear();
slpt.clear();
flag = true;
mint=2*T;
for(int i=0;i<N;i++)
{
getline(cin, tmp, '-');
st = transto(tmp);
getline(cin, tmp, '\n');
ed = transto(tmp);
if(st > ed) ed += T;
if(st < mint) mint=st;
tp.push_back({st, "s"});
tp.push_back({ed, "e"});
}
sort(tp.begin(), tp.end());
tp.push_back({mint+T, "s"});
n=tp.size()-1;
b = 0;
int first = 0;
for(int i=0;i<n;i++)
{
dt = tp[i+1].t - tp[i].t;
if(tp[i].st == "s")
{
b += dt+1;
if(b > B)
{
flag = false;
break;
}
}
else
{
if(dt-1 >= A)
{
slpt.push_back(transback((tp[i].t+1) % T) + "-" + transback((tp[i+1].t-1) % T));
if(!first) first = b;
b = 0;
}
else
{
b += dt-1;
if(b > B)
{
flag = false;
break;
}
if(i == n-1 && b+first>B)
{
flag=false;
break;
}
}
}
}
if(slpt.empty()) flag=false;
if(flag)
{
cout<<"Yes"<<endl;
cout<<slpt.size()<<endl;
for(int i=0, l=slpt.size();i<l;i++) cout<<slpt[i]<<endl;
}
else
{
cout<<"No"<<endl;
}
}
return 0;
}