题目链接
1229. 日期问题 - AcWing题库
一些话
切入点
// 小明知道这些日期都在1960年1月1日至2059年12月31日。
// 这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的
// 年份也都省略了前两位
// 多个日期按从早到晚排列。
// 读题可知以上四条日期要满足的情况,题目的切入点
流程
// 输出符合条件的情况,本质上和求符合条件情况的数量一样,所以这也是要用枚举的特征之一
// 要求满足多种性质的情况,首先要思考如何降低题目的复杂性,想下枚举什么可以直接满足更多的性质,枚举什么更加简单。
// 比如此题可以枚举合法日期,可以枚举日期区间内,可以枚举输入数据的不同排列。
// 如果枚举合法日期和日期区间内,再判断是否是输入数据的符合题意的排列的话就可以直接满足第四个性质,不需要储存数据然后再排序
// 枚举合法日期的难度较高,所以选择枚举日期区间内,然后再判断日期是否合法,是否符合排列比较简单
套路
日期类问题判断日期是否合法
int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; bool check(int year,int month,int day){ if(!day || months[month] < day && month != 2) return false; if(!month || month > 12) return false; if(month == 2){ if(day > 28 + (year % 100 && year % 4 == 0 || year % 400 == 0)) return false; } return true; }
ac代码
// 8:03-8:17思路错误 //判断日期是否合法不熟 // 10:30~10:35; // ~11:01accepted // 11:02~11:10 wa1 && accepted #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; // 日期合法判断不够熟练 int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; bool check(int year,int month,int day){ if(!day || months[month] < day && month != 2) return false; if(!month || month > 12) return false; if(month == 2){ if(day > 28 + (year % 100 && year % 4 == 0 || year % 400 == 0)) return false; } return true; } int main(){ int a,b,c; scanf("%d/%d/%d/",&a,&b,&c);//同航班时间的读取技巧 for(int i = 19600101;i <= 20591231;i++){ int year = i / 10000 % 100; int month = i % 10000 / 100; int day = i % 100; if(a == year && b == month && c == day && check(a,b,c) || a == month && b == day && c == year && check(c,a,b) || a == day && b == month && c == year && check(c,b,a)) printf("%d-%02d-%02d\n",i / 10000,month,day);//同航班时间的前导0补齐输出 } return 0; }