做了20道ccf的t3,这道题跟带配额的文件系统绝对是最恶心的两道题了。
光敲代码敲了俩小时,debug了一个小时才过样例。好在给的样例不错,调试过样例之后提交就直接AC了,心里得到了些许安慰。
输入是n条配置信息,配置信息的格式在题目中给出了,依次是分钟,小时,天数,月份,以及星期几。可以设置一个如下结构体,代表一个任务。数组大小是5,0-4分别对应分钟,小时,天数,月份,星期几五个属性。题目中说*代表任意取值,所以all[i]为真代表可以任意取值。ele[i][j]为真代表第i个属性可以取值为j。其中分钟是60进制,所以数组大小要大于60.
name很显然是该任务的名称。
采用数组可以通过循环减少代码量。
struct TASK{
bool all[5];
bool ele[5][100];
string name;
TASK(){memset(all,false,sizeof(all));
memset(ele,false,sizeof(ele));}
};
对于每个属性的取值,题目中说可以是'*',也可以带'-',还可以有','
其中'-'和','还可以同时出现
我采用字符串流的方式来分割字符串
首先getline读取整行,通过空格,我们可以将一行分解成六部分,前五部分是五个属性,第六部分是该任务的名字。然后处理分离得到的五个属性。此时属性可能包含'-'和','
我们通过将’,'替换成' ',可以再次利用字符串流分离到只带'-'或者什么也不带的属性的取值。
我们可以通过map,存储月份,星期的缩写对应的数字,题目中说不区分大小写,而且还可能有前缀零,这些都需要注意。我们map中存储的可以都是小写的,然后处理数据的时候,将英文缩写转换成小写再去查找map。
通过上述处理,我们就可以得到每个任务的可能取值。
接着就应该处理时间了,题目中提到Cron每分钟检查一次系统时间,而且时间给的是10s,不难得出,逐分钟遍历应该是不会TLE的。
怎么逐分钟遍历呢?我们可以写个函数,每小时60分钟,每天24h,每月若干天,每年12个月。每次我们(分钟+1)%60,如果结果是0,说明是新的一个小时,然后(小时+1)%24。。。后续同理,要注意判断闰年还是平年。
当当前时间处于题目给定的起始时间和结束时间之间的时候,我们对n个任务逐个判断当前时刻是否全部满足该任务的五个属性,然后进行相应的输出就可以。
完整代码如下
#include<bits/stdc++.h>
#define rep(i,start,end) for(int i=start;i<=end;i++)
using namespace std;
typedef long long LL;
typedef pair<LL,LL> pa;
int n;
int s[5],t[5];
map<string,int> dic;
bool year[2500];//是否是闰年
int m1[]={0,31,29,31,30,31,30,31,31,30,31,30,31};//每月多少天
int m2[]={0,31,28,31,30,31,30,31,31,30,31,30,31};//每月多少天
bool judge(int year)//是否是闰年
{
if(year%400==0)return true;
if(year%4==0&&year%100!=0)return true;
return false;
}
void init()
{
dic["jan"]=1,dic["feb"]=2,dic["mar"]=3,
dic["apr"]=4,dic["may"]=5,dic["jun"]=6,
dic["jul"]=7,dic["aug"]=8,dic["sep"]=9,
dic["oct"]=10,dic["nov"]=11,dic["dec"]=12;
dic["sun"]=0,dic["mon"]=1,dic["tue"]=2,dic["wed"]=3,
dic["thu"]=4,dic["fri"]=5,dic["sat"]=6;
for(int i=1970;i<=2100;i++)
year[i]=judge(i);
}
struct TASK{
bool all[5];
bool ele[5][100];
string name;
TASK(){memset(all,false,sizeof(all));
memset(ele,false,sizeof(ele));}
};
vector<TASK> task(25);
int tolow(string str)//将缩写转换成全小写
{
bool isnum=true;
for(auto t:str)
if(!isdigit(t)){
isnum=false;
break;
}
if(isnum)return stoi(str);//去掉多余的前缀0
string ans;//返回全小写的
for(auto t:str)
ans+=tolower(t);
return dic[ans];
}
void solve(int x,string line)
{
vector<string> v;
istringstream ss(line);
string str;
while(ss>>str)v.push_back(str);//代表各个日期
task[x].name=v[5];
for(int i=0;i<5;i++){
if(v[i]=="*"){
//!!!插入全部的
task[x].all[i]=true;//代表全部可以
continue;
}
int index=0;
while((index=v[i].find(',',index))!=v[i].npos){
v[i][index]=' ';
index++;
}
vector<string> date;//根据,分割后的日期
istringstream tmpss(v[i]);
while(tmpss>>str)date.push_back(str);//包含-的,各种写法
for(auto t:date){
int index=0;
if((index=t.find('-',index))!=str.npos){//代表存在减号
int l,r;
l=tolow(t.substr(0,index)),r=tolow(t.substr(index+1));
for(int j=l;j<=r;j++)
task[x].ele[i][j]=true;
}
else{//不存在减号
task[x].ele[i][tolow(t)]=true;
}
}
}
}
bool lesser(int a[],int b[])
{
for(int i=0;i<5;i++){
if(a[i]<b[i])return true;
if(a[i]>b[i])return false;
}
return false;
}
void pluser(int a[],int &week)
{
//加1分钟
a[4]=(a[4]+1)%60;//分钟
if(a[4])return ;
a[3]=(a[3]+1)%24;//小时
if(a[3])return ;
week=(week+1)%7;
if(year[a[0]]){//闰年
if(a[2]==m1[a[1]]){//是当月最后一天
a[2]=1;
}
else{
a[2]++;
return ;
}
if(a[1]==12){
a[1]=1;
}
else{
a[1]++;
return ;
}
a[0]++;
}
else{
if(a[2]==m2[a[1]]){//是当月最后一天
a[2]=1;
}
else{
a[2]++;
return ;
}
if(a[1]==12){
a[1]=1;
}
else{
a[1]++;
return ;
}
a[0]++;
}
}
void print(int now[],string& name)
{
for(int i=0;i<5;i++){
if(now[i]<10)cout<<0;
cout<<now[i];
}
cout<<" "<<name<<endl;
}
void func()
{
int now[]={1970,1,1,0,0};
int week=4;
while(lesser(now,t)){//没到截止时间
if(!lesser(now,s)&&lesser(now,t)){//代表在合理时间
for(int i=1;i<=n;i++){
if((task[i].all[0]||task[i].ele[0][now[4]])&&
(task[i].all[1]||task[i].ele[1][now[3]])&&
(task[i].all[2]||task[i].ele[2][now[2]])&&
(task[i].all[3]||task[i].ele[3][now[1]])&&
(task[i].all[4]||task[i].ele[4][week])
)
print(now,task[i].name);
}
}
pluser(now,week);
}
}
int main()
{
// freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
std::ios::sync_with_stdio(false);
init();
string s1,s2;
cin>>n>>s1>>s2;
s[0]=stoi(s1.substr(0,4)),s[1]=stoi(s1.substr(4,2)),s[2]=stoi(s1.substr(6,2)),s[3]=stoi(s1.substr(8,2)),s[4]=stoi(s1.substr(10,2));;
t[0]=stoi(s2.substr(0,4)),t[1]=stoi(s2.substr(4,2)),t[2]=stoi(s2.substr(6,2)),t[3]=stoi(s2.substr(8,2)),t[4]=stoi(s2.substr(10,2));;
string str;
getline(cin,str);
for(int i=1;i<=n;i++){
getline(cin,str);
solve(i,str);
}
func();
}