Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=3700
【前言】
终于又A了一道恶心的模拟题。
看来HDU恶心题还是蛮多的。
【思路】
扫描一遍,如果有时间段大于b的,则输出No。
时间段是不会重叠的。所以先按时间段排序。如果间隔时间大于a,则先休息。把休息的时间段记录起来。
否则把下一段时间归并到当前时间段。
同时判断当前时间段是否大于b,是则输出No。
如果最后一个时间段的结束时间与第一个时间的开始时间的间隔大于等于a,说明可以分割。
否则需要查看当前时间段是否可以连接到第一个时间段前面。
注意,如果休息的时间段跨夜,则直接输出,如:23:00-1:00(不需要分成两段写)。
如果没有休息的时间段,则应输出No。
【代码】
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 20;
const int day = 24*60;
struct node
{
int s;
int e;
}pt[maxn+5];
vector<node>v;
bool cmp(const node &a, const node &b)
{
return a.s<b.s;
}
void show(node temp)
{
printf("%d%d:%d%d-%d%d:%d%d\n", temp.s/600, temp.s/60%10, temp.s%60/10, temp.s%10, temp.e/600, temp.e/60%10, temp.e%60/10, temp.e%10);
}
int main()
{
int a, b;
int n;
int i;
bool fail;
char str[20];
node temp, x;
while(scanf("%d %d", &a, &b)!=EOF)
{
a *= 60;
b *= 60;
scanf("%d", &n);
for (i=1; i<=n; i++)
{
scanf("%s", str);
pt[i].s = (str[0]-'0')*600+(str[1]-'0')*60+(str[3]-'0')*10+(str[4]-'0');
pt[i].e = (str[6]-'0')*600+(str[7]-'0')*60+(str[9]-'0')*10+(str[10]-'0');
if (pt[i].e<pt[i].s) pt[i].e += day;
}
sort(pt+1, pt+n+1, cmp);
v.clear();
fail = false;
for (i=1; i<=n; i++)
{
if (pt[i].e-pt[i].s+1>b)
{
fail = true;
break;
}
}
if (!fail)
{
temp.s = pt[1].s;
temp.e = pt[1].e;
for (i=1; i<n; i++)
{
if (pt[i+1].s-1-temp.e>=a)
{
x.s = temp.e+1;
x.e = pt[i+1].s-1;
if (x.s!=x.e) v.push_back(x);
temp.s = pt[i+1].s;
temp.e = pt[i+1].e;
}
else
{
temp.e = pt[i+1].e;
if (temp.e-temp.s+1>b)
{
fail = true;
break;
}
}
}
}
if (!fail)
{
if (pt[1].s+day-1-temp.e>=a)
{
x.s = (temp.e+1)%day;
x.e = (pt[1].s-1+day)%day;
if (x.s!=x.e) v.push_back(x);
}
else if (v.size()>0 && (v[1].s-1+day)%day-temp.s+1<=b)
{
}
else fail = true;
}
if (fail || v.size()==0)
printf("No\n");
else
{
printf("Yes\n%d\n", v.size());
sort(v.begin(), v.end(), cmp);
for (i=0; i<v.size(); i++)
show(v[i]);
}
}
return 0;
}
继续寻找恶心的模拟题……