题目描述:
TA团队每周都会有很多任务,有的可以单独完成,有的则需要所有人聚到一起,开过会之后才能去做。但TA团队的每个成员都有各自的事情,找到所有人都有空的时间段并不是一件容易的事情。
给出每位助教的各项事情的时间表,你的任务是找出所有可以用来开会的时间段。
input:
第一行一个数T(T≤100),表示数据组数。
对于每组数据,第一行一个数m(2 ≤ m ≤ 20),表示TA的数量。
对于每位TA,首先是一个数n(0≤ n≤100),表示该TA的任务数。接下来n行,表示各个任务的信息,格式如下
YYYY MM DD hh mm ss YYYY MM DD hh mm ss "some string here"
每一行描述的信息为:开始时间的年、月、日、时、分、秒;结束时间的年、月、日、时、分、秒,以及一些字符串,描述任务的信息。
数据约定:
所有的数据信息均为固定位数,位数不足的在在前面补前导0,数据之间由空格隔开。
描述信息的字符串中间可能包含空格,且总长度不超过100。
所有的日期时间均在1800年1月1日00:00:00到2200年1月1日00:00:00之间。
为了简化问题,我们假定所有的月份(甚至2月)均是30天的,数据保证不含有不合法的日期。
注意每件事务的结束时间点也即是该成员可以开始参与开会的时间点。
output:
对于每一组数据,首先输出一行"Scenario #i:",i即表明是第i组数据。
接下来对于所有可以用来开会的时间段,每一个时间段输出一行。
需要满足如下规则:
- 在该时间段的任何时间点,都应该有至少两人在场。
- 在该时间段的任何时间点,至多有一位成员缺席。
- 该时间段的时间长度至少应该1h。
所有的成员都乐意一天24h进行工作。
举个例子,假如现在TA团队有3位成员,TT、zjm、hrz。
那么这样的时间段是合法的:会议开始之初只有TT和zjm,后来hrz加入了,hrz加入之后TT离开了,此后直到会议结束,hrz和zjm一直在场。
要求:
- 输出满足条件的所有的时间段,尽管某一段可能有400年那么长。
- 时间点的格式为MM/DD/YYYY hh:mm:ss。
- 时间段的输出格式为"appointment possible from T0 to T1",其中T0和T1均应满足时间点的格式。
- 严格按照格式进行匹配,如果长度不够则在前面补前导0。
- 按时间的先后顺序输出各个时间段。
- 如果没有合适的时间段,输出一行"no appointment possible"。
- 每组数据末尾须打印额外的一行空行。
思路:
一个区间调度问题,但与普通的区间调度不同的是,有T组数据(这个条件可以忽略),有n个人,每个人又有mi件事情,每件事情对应了一个区间。这类似于n条时间轴,每个时间轴上有mi个区间的问题。
现在考虑可以开会的条件:1、至少有2个人。2、顶多缺席一人。3、开会时长大于等于1小时(这个可以暂时忽略,最后判断时间差即可)。开会的条件有人数的限制,因此编程时需要考虑人数。为解决这个问题,将n条时间轴浓缩成一条,如果a在此时有事,则时间轴该时刻对应的值+1,如果b在此时也有事,时间轴再次+1。这就形成了在时间轴上若干个区间,区间内所有的数+1的问题。
由于时间轴持续了上千年,过于庞大,遍历赋值的方法不可能实现,所以考虑差分:在开始时刻+1,表示从现在开始,某个人忙了起来。结束时刻-1,表示从现在开始,这个人忙完了。同样由于时间轴过于庞大,但是区间可能会较少,开数组用数组下标表示时刻的方法也不能实现,因此考虑map(同样也是因为map可以自动排序,方便遍历)。
一些细节:输入时,观察到:对于某见事情,输入的起始时间和结束时间,相当于12个数,虽然会出现00分、03秒这样的情况,但这同时也是int类型的0和3,因此对于每件事情直接读入12个int即可。后面还跟着可能出现空格的字符串,这时候直接getline即可(这里的字符串对本题没有任何意义)。读入后,将起始时间转换成long long,如:1800年01月01日00时00分00秒转换为:18000101000000,long long恰好可以存开。
如何判断两个时刻是否相差一个小时之内?将时刻转换成秒即可,从0年1月1日00时00分00秒开始计算。若time2-time1>=3600,则可以判断两个时刻相差大于一小时。
#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
long long d1=12,d2=30,d3=24,d4=60,d5=60;
long long year,mon,day,hour,mi,sec;
string c;
map<long long,int> ha;
struct node
{
vector<pair<long long,long long> > t;
}a[110];
long long num(long long x)
{
long long ans=0;
sec=x%100;
x/=100;
mi=x%100;
x/=100;
hour=x%100;
x/=100;
day=x%100;
x/=100;
mon=x%100;
x/=100;
year=x;
ans=ans+year*d1*d2*d3*d4*d5;
ans=ans+(mon-1)*d2*d3*d4*d5;
ans=ans+(day-1)*d3*d4*d5;
ans=ans+hour* d4*d5;
ans=ans+mi*d5;
ans=ans+sec;
return ans;
}
bool judge(long long a,long long b)//a>=b,判断时间a-b是不是大于一个小时
{
if(num(a)-num(b)>=3600)
return true;
return false;
}
void output(long long x)//以01/01/1800 00:00:00格式输出
{
sec=x%100;
x/=100;
mi=x%100;
x/=100;
hour=x%100;
x/=100;
day=x%100;
x/=100;
mon=x%100;
x/=100;
year=x;
if(mon<10)
cout<<0<<mon<<'/';
else cout<<mon<<'/';
if(day<10)
cout<<0<<day<<'/';
else cout<<day<<'/';
cout<<year<<" ";
if(hour<10)
cout<<0<<hour<<':';
else cout<<hour<<':';
if(mi<10)
cout<<0<<mi<<':';
else cout<<mi<<':';
if(sec<10)
cout<<0<<sec;
else cout<<sec;
}
int main()
{
int T,n,m;
cin>>T;
for(int lll=1;lll<=T;lll++)
{
ha.clear();
int tot=0;
cin>>n;
for(int i=1;i<=n;i++)//n个人
{
cin>>m;//每个人m件事
if(m==0) continue;
++tot;
for(int j=1;j<=m;j++)
{
pair<long long,long long> tmp;
cin>>year>>mon>>day>>hour>>mi>>sec;
long long l=(((((year*100+mon)*100+day)*100+hour)*100+mi)*100+sec);
tmp.first=l;
cin>>year>>mon>>day>>hour>>mi>>sec;
l=(((((year*100+mon)*100+day)*100+hour)*100+mi)*100+sec);
tmp.second=l;
a[tot].t.push_back(tmp);
ha[a[tot].t[j-1].first]++;
ha[a[tot].t[j-1].second]--;
getline(cin,c);
}
}
cout<<"Scenario #"<<lll<<":"<<endl;
long long from=18000101000000,to=22000101000000;
bool flag=0;ha[to]=-1;
long long busy=0,maxx=0,minn=from;
for(map<long long,int>::iterator it=ha.begin();it!=ha.end();it++)
{
long long tmp1=it->first,tmp2=it->second;
busy+=tmp2;
if(busy<=1&&n-busy>=2)//在此刻可以开会了,记录起始时间 minn
{
maxx=tmp1;
minn=min(minn,tmp1);
}
else//会议结束,记录结束时间maxx
{
maxx=tmp1;
if(judge(maxx,minn))//保证maxx一定比minn大
{
flag=true;
cout<<"appointment possible from ";
output(minn);
cout<<" to ";
output(maxx);
cout<<endl;
}
minn=to;
}
}
maxx=to;
if(judge(maxx,minn))
{
flag=true;
cout<<"appointment possible from ";
output(minn);
cout<<" to ";
output(maxx);
cout<<endl;
}
if(!flag)
cout<<"no appointment possible"<<endl;
cout<<endl;
/*for(int i=1;i<=tot;i++)
{
for(int j=0;j<a[i].t.size();j++)
cout<<a[i].t[j].first<<" "<<a[i].t[j].second<<endl;
}*/
for(int i=1;i<=tot;i++)
a[i].t.clear();
}
return 0;
}