真实的昨天晚上开始,今天做了一上午,好多次整个代码推倒重来,最后只有85.。。
我本来想的呀,如果我做出来了这么麻烦的一道题,我的耐心就上了一个台阶,,但是现在我实在找不到哪里错了,错误的样例报的是运行错误,可能是超时这种?这个坑我今天补不起来了
思路:
1、先把月日时分星期几每个都看成单独的个体,互不影响,所以叫初步筛选,用几个数组months[],days[],hours[],minutes[],weekdays[],对应的满足条件为1,不满足为0,在这一部分处理了特殊符号的情况
2、按照年月日时分的顺序遍历,这一块比较卡的就是遍历的时候的开始时间和结束时间的确定了。
注意:
1、整个题目里边细节太多了,我觉得静下心来给自己足够的时间应该能捋清楚
2、还有一个想给自己提个醒的,不要偷懒复制粘贴某一段然后改名到下一段,血的教训啊!!!总有忘改名字的时候,然后就成了永远找不到的bug
自测样例:
题目给的测试样例正确但是还没有满分时,自己创了一些自测样例,提到了85分(但事实上,下边的大部分样例都是改了我自己的bug!!!但是没有提分,最后还是85 o(╥﹏╥)o)
总结一下这些点就是:闰年,二月,跨日(23:59,00:00),跨月,跨年
1 200001190000 200003020000 //检查闰年二月份的天数是否正确
0 0 * * * day
1 201711170032 201711170033 //s包含,t不包含
* * * * * hello
输出:
201711170032 hello
1 201711172358 201711180001 //
* * * * * hello
输出:
201711172358 hello
201711172359 hello
201711180000 hello
1 201711172359 201711180001 //23:59这个时间本来就是一个比较特殊的时间。(包含)到第二天的交界处
* * * * * hello
输出:
201711172359 hello
201711180000 hello
1 201711172358 201711180000 //00:00也是一个比较特殊的时间。结束时间到00:00的情况
* * * * * hello
输出:
201711172358 hello
201711172359 hello
1 201712312359 201801010003 //跨年的
* * * * * hello
输出:
201712312359 hello
201801010000 hello
201801010001 hello
201801010002 hello
85分代码:
#include<iostream>
#include<map>
#include<queue>
#include<cstring>
#include<vector>
using namespace std;
const int minmonth=1,maxmonth=12;
const int minday=1,maxday=31;
const int minhour=0,maxhour=23;
const int minminute=0,maxminute=59;
const int minweekday=0,maxweekday=6;
string weekdaytable[8]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
string monthtable[13]= {"","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
int monthday[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; //注意最开始要多加一个0,这样才能对应
struct time {
int year;
int month;
int day;
int hour;
int minute;
bool operator <(time x)const { //重载<
if(year!=x.year) return year>x.year;
else {
if(month!=x.month) return month>x.month;
else {
if(day!=x.day) return day>x.day;
else {
if(hour!=x.hour) return hour>x.hour;
else {
return minute>x.minute;
}
}
}
}
}
};
int leapyear(int year) { //是否为闰年,是返回1,否返回0
if((year%4==0 && year%100!=0) || year%400==0) return 1;
return 0;
}
// 适用于1582年10月15日之后, 因为罗马教皇格里高利十三世在这一天启用新历法
// 蔡勒公式:给定年月日,得到当天是星期几
int weekday(int year,int month,int day) {
if(month == 1 || month == 2) {
month += 12;
year--;
}
int c = year / 100;
int y = year % 100;
int m = month;
int d = day;
int w = c / 4 - 2 * c + y + y / 4 + 26 * (m + 1) / 10 + d - 1;
if(w < 0)
return (w + (-w / 7 + 1) * 7) % 7;
return w % 7;
}
time stotime(string s) { //将输入的字符串yyyymmddHHMM转化成time结构体
time t;
t.year=(s[0]-'0')*1000+(s[1]-'0')*100+(s[2]-'0')*10+(s[3]-'0');
t.month=(s[4]-'0')*10+(s[5]-'0');
t.day=(s[6]-'0')*10+(s[7]-'0');
t.hour=(s[8]-'0')*10+(s[9]-'0');
t.minute=(s[10]-'0')*10+(s[11]-'0');
return t;
}
//字符串转为整形
int stringtoint(string s) {
int res=0;
for(int i=0; i<s.length(); i++) {
res*=10;
res+=s[i]-'0';
}
return res;
}
//年月日时分秒转化成输出的时间格式并添加前导零
string inttostring(int year,int month,int day,int hour,int minute) {
string res="";
res+=year/1000+'0';
year%=1000;
res+=year/100+'0';
year%=100;
res+=year/10+'0';
year%=10;
res+=year+'0';
res+=month>=10? '1':'0';
res+=month%10+'0';
res+=day>=10? day/10+'0':'0';
res+=day%10+'0';
res+=hour>=10? hour/10+'0':'0';
res+=hour%10+'0';
res+=minute>=10? minute/10+'0':'0';
res+=minute%10+'0';
return res;
}
//处理有,-的情况
vector<int> process(string s) {
vector<int> res;
string temp;
while(s.find(',')!=string::npos) { //先按,分开
temp=s.substr(0,s.find(','));
if(temp.find('-')!=string::npos) { //有-
int start=stringtoint(temp.substr(0,temp.find('-')));
int end=stringtoint(temp.substr(temp.find('-')+1));
for(int i=start; i<=end; i++) {
res.push_back(i);
}
} else { //没有-,说明是一个纯数字
res.push_back(stringtoint(temp));
}
s=s.substr(s.find(',')+1);
}
//处理有逗号的字符串中剩下的最后一个字符串或者一开始就没有逗号的字符串
if(s.find('-')!=string::npos) { //没有,只有-
int start=stringtoint(s.substr(0,s.find('-')));
int end=stringtoint(s.substr(s.find('-')+1));
for(int i=start; i<=end; i++) {
res.push_back(i);
}
} else { //没有,没有- 只有单个数字
res.push_back(stringtoint(s));
}
return res;
}
//初步筛选满足条件的年月日时分(筛选日时未考虑星期几
//输入字符串,最小值,最大值,函数处理后改变temprecord的值,在主函数中对相应数组进行赋值
int temprecord[61];
void select(string input,int minvalue,int maxvalue) {
memset(temprecord,0,sizeof(temprecord));
if(input=="*") {
//所有月份
for(int i=minvalue; i<=maxvalue; i++) {
temprecord[i]=1;
}
} else if((input.length()==2 && input[0]-'0'>=0 && input[0]-'0'<=9 && input[1]-'0'>=0 && input[1]-'0'<=9 ) || (input.length()==1 && input[0]-'0'>=0 && input[0]-'0'<=9 )) {
//某一个单个月份
int temp=stringtoint(input);
temprecord[temp]=1;
}
//里边有, -的多个月份
else {
vector<int> res;
res=process(input);
for(int i=0; i<res.size(); i++) {
temprecord[res[i]]=1;
}
}
}
struct final {
string tm;
string command;
bool operator < (final x)const {
return tm>=x.tm;
}
};
priority_queue<final> finally; //按时间从小到大的顺序排列,记录最终结果
int main() {
int n;
string s,t;
cin>>n>>s>>t;
time stime=stotime(s);
time ttime=stotime(t);
for(int i=0; i<n; i++) {
string minute,hour,daym,month,dayw,command;
cin>>minute>>hour>>daym>>month>>dayw>>command;
time t;
//将含有字母的month转化成整数
// month=t(month);
string monthtemp="";
for(int j=0; j<month.length(); j++) {
if(month[j]>='A'&&month[j]<='Z') {
string mtp="";
mtp+=month[j++];
mtp+=month[j++];
mtp+=month[j];
for(int k=1; k<=12; k++) {
if(mtp==monthtable[k]) {
if(k>=10) monthtemp+=k/10+'0';
monthtemp+=k%10+'0';
break;
}
}
} else {
monthtemp+=month[j];
}
}
month=monthtemp;
// //将星期几转化成整数
string weekdaytemp="";
for(int j=0; j<dayw.length(); j++) {
if(dayw[j]>='A'&&dayw[j]<='Z') {
string mtp="";
mtp+=dayw[j++];
mtp+=dayw[j++];
mtp+=dayw[j];
for(int k=0; k<=6; k++) {
if(mtp==weekdaytable[k]) {
weekdaytemp+=k%10+'0';
break;
}
}
} else {
weekdaytemp+=dayw[j];
}
}
dayw=weekdaytemp;
//筛选满足条件的月份
int months[maxmonth+1]; //month[i]=1表示i月满足条件
select(month,minmonth,maxmonth);
for(int i=minmonth; i<=maxmonth; i++) {
months[i]=temprecord[i];
}
//满足条件的日(此处还未考虑具体月份的天数、星期几对不对,因为星期几还需要在特定的年月日才能计算
int days[maxday+1];
select(daym,minday,maxday);
for(int i=minday; i<=maxday; i++) {
days[i]=temprecord[i];
}
//筛选满足条件的小时
int hours[maxhour+1];
select(hour,minhour,maxhour);
for(int i=minhour; i<=maxhour; i++) {
hours[i]=temprecord[i];
}
//筛选满足条件的分钟
int minutes[maxminute+1];
select(minute,minminute,maxminute);
for(int i=minminute; i<=maxminute; i++) {
minutes[i]=temprecord[i];
}
//满足条件的星期几
int weekdays[maxweekday+1];
select(dayw,minweekday,maxweekday);
for(int i=minweekday; i<=maxweekday; i++) {
weekdays[i]=temprecord[i];
}
//开始模拟
int j,k,p,q,r;
int startyear=stime.year,endyear=ttime.year;
for(j=startyear; j<=endyear; j++) { //输入的contrab对年没有限制
int startmonth=stime.month,endmonth=ttime.month;
int cursmonth=(j==startyear)?startmonth:minmonth; //j年的开始月份(包含)
int curemonth=(j==endyear)?endmonth:maxmonth; //j年的结束月份(包含)
for(k=cursmonth; k<=curemonth; k++) { //遍历j年的各个月
if(months[k]!=1) continue;
int startday=stime.day, endday=ttime.day;
int cursday=(j==startyear && k==startmonth)?startday:minday; //j年k月的开始天数(包含)
int cureday=(j==endyear && k==endmonth)?endday:(monthday[k]+(k==2?leapyear(j):0)); //j年k月的结束天数(包含) 考虑是否为闰年、二月份
for(p=cursday; p<=cureday; p++) {
if(days[p]!=1 || weekdays[weekday(j,k,p)]!=1) continue; //要考虑天数+星期几对不对
int starthour=stime.hour,endhour=ttime.hour;
int curshour=(j==startyear && k==startmonth && p==startday)?starthour:minhour; //j年k月p日的开始小时 (包含)
int curehour=(j==endyear && k==endmonth && p==endday)?endhour:maxhour; //j年k月p日的结束小时 (包含)
for(q=curshour; q<=curehour; q++) {
if(hours[q]!=1) continue;
int startminute=stime.minute,endminute=ttime.minute;
int cursminute=(j==startyear && k==startmonth && p==startday && q==starthour)?startminute:minminute; //j年k月p日q时的开始分钟 (包含)
int cureminute=(j==endyear && k==endmonth && p==endday && q==endhour)?endminute-1:maxminute; //j年k月p日q时的结束分钟 (不包含),最后一分钟不包含,所以是endminute-1
if(cureminute==-1) continue;
for(r=cursminute; r<=cureminute; r++) {
if(minutes[r]!=1) continue;
else {
final f;
f.tm=inttostring(j,k,p,q,r);
f.command=command;
finally.push(f) ;
}
}
}
}
}
}
}
while(!finally.empty()) {
final f=finally.top();
cout<<f.tm<<" "<<f.command<<endl;
finally.pop();
}
return 0;
}