这是ccf第三题中近年来博主见过的比较恶心的模拟题,涉及到模拟+文本处理,代码量较大。先看题目:
读完题目后,需要注意的几个地方:
1. 分钟、小时、天数、月数的取值范围
2. 分钟、小时前面可以有前导0
3. 大小写不区分
4. 时间的取值范围是左闭右开(博主当初没注意到,丢了30分,找了好几天才找到bug)
现在我们开始来寻找解题思路,很容易想到,从开始的时间到结束的时间,每一个时间都去寻找与之匹配的命令,符合则输出,但是这种很容易超时。所以采用另一种思路,找到每一项命令的执行时间,判断是否可以执行,这种思路比较清晰,也不会超时,可以做。下面看代码:
#include<bits/stdc++.h>
using namespace std;
long long star,end,syear,eyear;
set<long long> minu,hour,day,mon,we;
set<long long> temp;
struct nd{ //woek为命令,num为时间
long long num;
string work;
}endd[10000];
string Turn(string s) //','转' ';
{
int len=s.length();
for(int i=0;i<len;i++)
{
if(s[i]==',') s[i]=' ';
}
return s;
}
string Turnzm(string s) //大写转小写
{
long long len=s.length(),i;
for(i=0;i<len;i++)
{
if(s[i]>='A'&&s[i]<='Z') s[i]+=32;
}
return s;
}
long long Turn_int(string s) //该函数可以把题目的所有格式转换为数字
{
s=Turnzm(s);
if(s=="sun") return 0;
if(s=="jan"||s=="mon") return 1;
if(s=="feb"||s=="tue") return 2;
if(s=="mar"||s=="wed") return 3;
if(s=="apr"||s=="thu") return 4;
if(s=="may"||s=="fri") return 5;
if(s=="jun"||s=="sat") return 6;
if(s=="jul") return 7;
if(s=="aug") return 8;
if(s=="sep") return 9;
if(s=="oct") return 10;
if(s=="nov") return 11;
if(s=="dec") return 12;
long long res;
stringstream ss;
ss<<s;
ss>>res;
return res;
}
void inputt(long long i, long long p) //p代表该数据是分、小时、天、月或者周
{
if(p==1) //1代表min
{
minu.insert(i);
}
if(p==2) //2代表hour
{
hour.insert(i);
}
if(p==3) //1代表day
{
day.insert(i);
}
if(p==4) //4 mon
{
mon.insert(i);
}
if(p==5)
{
we.insert(i);
}
}
void Turntime(string s,long long p) //得到每一时间部分的数据
{
long long i,j;
if(s=="*")
{
if(p==1) //1代表min
{
for(long long i=0;i<60;i++)
{
inputt(i,p);
}
}
if(p==2) //2代表hour
{
for(long long i=0;i<24;i++)
{
inputt(i,p);
}
}
if(p==3) //3代表day
{
for(long long i=1;i<32;i++)
{
inputt(i,p);
}
}
if(p==4) //4 mon
{
for(long long i=1;i<13;i++)
{
inputt(i,p);
}
}
if(p==5) //5代表周
{
for(long long i=0;i<7;i++)
{
inputt(i,p);
}
}
return ;
}
s=Turn(s); //把','转化为' '
stringstream ss(s);
string st;
while(ss>>st&&!st.empty())
{
long long ans=st.find('-');
if(ans!=string::npos)
{
for(i=Turn_int(st.substr(0,ans));i<=Turn_int(st.substr(ans+1));i++ ) //-两边的数字
{
inputt(i,p);
}
}
else inputt(Turn_int(st),p);
}
}
long long weekday(long long n) //判断星期几
{
n=n/10000;
long long y=n/10000;n=n%10000;long long m=n/100;n=n%100;long long d=n;
long long cday=0;
long long monday[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
for(long long i=1970;i<y;i++)
{
if((i%4==0&&i%100!=0)||i%400==0)
cday+=366;
else
cday+=365;
}
if((y%4==0&&y%100!=0)||y%400==0) monday[2]=29;
else monday[2]=28;
for(long long i=1;i<m;i++)
{
cday+=monday[i];
}
cday=cday+d-1;
cday=cday%7;
if(cday==0) return 4;
if(cday==1) return 5;
if(cday==2) return 6;
if(cday==3) return 0;
if(cday==4) return 1;
if(cday==5) return 2;
if(cday==6) return 3;
}
bool pd_week(long long n) //筛选判断星期
{
set<long long>::iterator p2;
for(p2=we.begin();p2!=we.end();p2++)
{
if(weekday(n)==*p2)
{
return true;
}
}
return false;
}
long long mon_day(long long m,long long y) //该月含有的天数
{
if(m==2)
{
if((y%400)==0||(y%4==0&&y%100!=0))
return 29;
else
return 28;
}
if(m==1||m==3||m==5||m==7||m==8||m==10||m==12)
return 31;
else
return 30;
}
bool pd(long long n) //判断合法的日期和符合题目的时间
{
if(!pd_week(n)) return false;
if(n<star||n>=end) return false;
n=n/10000;
long long y=n/10000;n=n%10000;long long m=n/100;n=n%100;long long d=n;
if(mon_day(m,y)>=d) return true;
return false;
}
bool cmp(nd a, nd b) //排序函数
{
return a.num<b.num;
}
int main()
{
long long i,j,k=0,n;
cin>>n>>star>>end;
syear=star/100000000;
eyear=end/100000000;
cin.get();
for(i=0;i<n;i++)
{
string s,st;
minu.clear(); hour.clear(); day.clear(); mon.clear();we.clear();temp.clear();
getline(cin,s);
stringstream ss(s);
for(j=1;j<=5;j++) //用流提取出五个部分,分别转化得到数字
{
ss>>st;
Turntime(st,j); //得到组合
}
set<long long>::iterator p1,p2,p3,p4;
for(j=syear;j<=eyear;j++)
{
for(p4=mon.begin();p4!=mon.end();p4++)
{
for(p3=day.begin();p3!=day.end();p3++)
{
for(p2=hour.begin();p2!=hour.end();p2++)
{
for(p1=minu.begin();p1!=minu.end();p1++)
{
long long res=j*100000000+(*p4)*1000000+(*p3)*10000+(*p2)*100+(*p1);
temp.insert(res);
}
}
}
}
}
ss>>st; //work
for(p1=temp.begin();p1!=temp.end();p1++) //判断,符合则存到数组中
{
if(pd(*p1))
{
endd[k].work =st;
endd[k++].num=*p1;
}
}
}
stable_sort(endd,endd+k,cmp);
for(i=0;i<k;i++)
cout<<endd[i].num <<' '<< endd[i].work<<endl; //输出
return 0;
}