1.解题思路
暴力,从开始时间s循环到结束时间e,以每分钟增加,遍历所有配置,看其值是否合法,合法输出相应的命令,求星期可以参考之前csp的节日,从1970年1月1日推导,或者用蔡勒公式直接算,对于配置的各项允许的值,首先判断是否等于‘*’,等于则将len长度的v数组全部置为一,表示0~len-1的值都是合法的,若不等于则以逗号为分隔符将字符串分割,再查找是否有-,没有直接将字符串转为对应数字或者月份或者星期,否则以-为参考将字符串一分为二,算出两端的值l,r将区间[l,r]的值全部置为一。
ps:这题debug到怀疑人生,需要注意输入的月份和星期不一定是标准输入(即开头大写后续小写),还有就是暴力带来的超时问题,一开始是用数组保存每个配置允许的值,只能拿80分,后来采用桶排序思想,空间换时间,加快很多。
2.满分代码
#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
//处理英文缩写
map<string,int> dic={{"jan",1},{"feb",2},{"mar",3},{"apr",4},{"may",5},{"jun",6},
{"jul",7},{"aug",8},{"sep",9},{"oct",10},{"nov",11},{"dec",12},
{"sun",0},{"mon",1},{"tue",2},{"wed",3},{"thu",4},{"fri",5},{"sat",6}};
//平年的每月天数
int mon[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int get(string s)
{
if(isdigit(s[0]))return stoi(s);
transform(s.begin(),s.end(),s.begin(),::tolower);
return dic[s];
}
int isleap(int y)
{
return ((y%400==0)||((y%4==0)&&(y%100!=0)))?1:0;
}
int weekday(int year,int month,int day)
{
int sum=0;
for(int i=1970;i<year;i++)
{
if(isleap(i))sum+=366;
else sum+=365;
}
for(int i=1;i<month;i++)
{
if(i==2&&isleap(year))sum+=29;
else sum+=mon[i];
}
sum+=day-1;
return (sum%7+4)%7;
}
vector<int> workstr(string str,int len)
{
vector<int>v(len);
if(str=="*")//len区间内都可以 1表示可以 0表示不可以
{
for(int i=0;i<len;i++)
{
v[i]=1;
}
}
else{
vector<string>val;
int p=str.find(",");
while(p!=-1)
{
val.push_back(str.substr(0,p));
str=str.substr(p+1);
p=str.find(",");
}
val.push_back(str);
for(auto s:val)//"-"
{
int p=s.find("-");
if(p==-1)v[get(s)]=1;
else
{
int l=get(s.substr(0,p));
int r=get(s.substr(p+1));
for(int i=l;i<=r;i++)
{
v[i]=1;
}
}
}
}
return v;
}
struct CMD
{
vector<int>v[5];
string cmd;
CMD(){
}
CMD(string s0,string s1,string s2,string s3,string s4,string c)
{
v[0]=workstr(s0,60);//minute
v[1]=workstr(s1,24);//hour
v[2]=workstr(s2,32);//day of month
v[3]=workstr(s3,13);//month
v[4]=workstr(s4,7);//day of week
cmd=c;
}
}C[26];
struct time{
int y,m,d,h,mi,w;
void add()
{
mi++;
if(mi==60)
{
mi=0;
h++;
if(h==24)
{
h=0;
d++;
w=(w+1)%7;
int tmp;
if((m==2)&&isleap(y))tmp=29;
else tmp=mon[m];
if(d>tmp)
{
d=1;
m++;
if(m==13)
{
m=1;
y++;
}
}
}
}
}
bool operator<(const time &t)const{
if(y!=t.y)return y<t.y;
if(m!=t.m)return m<t.m;
if(d!=t.d)return d<t.d;
if(h!=t.h)return h<t.h;
return mi<t.mi;
}
};
int main()
{
int n;
time s,e;
scanf("%d %04d%02d%02d%02d%02d %04d%02d%02d%02d%02d",&n,&s.y,&s.m,&s.d,&s.h,&s.mi,&e.y,&e.m,&e.d,&e.h,&e.mi);
s.w=weekday(s.y,s.m,s.d);//开始时间是星期几
e.w=weekday(e.y,e.m,e.d);//结束时间是星期几
for(int i=0;i<n;i++)
{
string s0,s1,s2,s3,s4,c;
cin>>s0>>s1>>s2>>s3>>s4>>c;
C[i]=CMD(s0,s1,s2,s3,s4,c);//每条配置信息
}
for(auto i=s;i<e;i.add())//从起始时间到结束时间按每分钟间隔增长
{
for(int j=0;j<n;j++)//n条配置信息
{
if(C[j].v[0][i.mi]&&C[j].v[1][i.h]&&C[j].v[2][i.d]&&C[j].v[3][i.m]&&C[j].v[4][i.w])
{
printf("%04d%02d%02d%02d%02d ",i.y,i.m,i.d,i.h,i.mi);
cout<<C[j].cmd<<endl;
}
}
}
return 0;
}