前置知识
输入解析
要会什么?
会用这一句把 AA/BB/CC 读进来:
cpp
int a,b,c;
scanf("%d/%d/%d", &a, &b, &c);
要记住什么?
"%d/%d/%d" 的意思是:
先读一个整数,接着必须遇到 / ,再读一个整数,再遇到 / ,再读一个整数
题目格式固定,所以不用担心空格、换行、乱格式
读进来的 a,b,c 都是 0~99 的两位数(比如 02 会读成整数 2)
两位年份到四位年份映射
要会什么?
把两位数的 yy 变成四位数年份:
cpp
int fullYear(int yy) {
return (yy <= 59) ? (2000 + yy) : (1900 + yy);
}
要记住什么?
题目限定最终年份只能在 1960~2059,所以映射只能是:
00~59 → 2000~2059
60~99 → 1960~1999
条件运算符 ?: 的读法:
条件 ? A : B
条件成立返回 A,否则返回 B
闰年判断
要会什么?
写一个函数判断 y 是否为闰年:
cpp
bool isLeap(int y) {
return (y % 400 == 0) || (y % 4 == 0 && y % 100 != 0);
}
要记住什么?
能被 400 整除是闰年
能被 4 整除且不能被 100 整除也是闰年
其他是平年
运算符优先级:&& 比 || 高,但写括号最稳
月份天数表 + 日期合法性判断
要会什么?
用数组存每月天数,并写 valid(y,m,d) 判断是否合法:
cpp
static int md[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
bool valid(int y, int m, int d) {
if (y < 1960 || y > 2059) return false;
if (m < 1 || m > 12) return false;
int days = md[m] + (m == 2 && isLeap(y)); // 闰年2月+1
return d >= 1 && d <= days;
}
要记住什么?
md[0]=0 只是占位,让月份 1~12 直接当下标好用。
days = md[m] + (m==2 && isLeap(y))
这里 (m==2 && isLeap(y)) 结果是 true/false,在 C/C++ 里会当 1/0 用。
三种日期格式枚举思想
要会什么?
输入 a/b/c 可能代表三种解释方式,所以只需要枚举这三种:
yy/mm/dd → (fullYear(a), b, c)
mm/dd/yy → (fullYear(c), a, b)
dd/mm/yy → (fullYear(c), b, a)
要记住什么?
这题不是"枚举所有天",而是"枚举所有解释方式",最多 3 个候选,极快。
每个候选都用 valid() 筛一下,合法的才收集。
排序 + 去重
要会什么
把收集到的候选日期排序,然后去掉重复项:
sort(ans.begin(), ans.end());
ans.erase(unique(ans.begin(), ans.end()), ans.end());
要记住什么
不用死记位置,知道 unique 会标记重复区起点,erase 删掉这个起点后的所有元素就够了。
容器与数据结构表达
要会什么?
用一个能自动按年-月-日排序的结构存答案:
vector<pair<int, pair<int,int>>> ans; // (y, (m, d))
插入时可以这样:
ans.push_back({y, {m, d}});
要记住什么?
pair 默认比较规则是字典序:
先比 first(年)
年相同再比 second.first(月)
月相同再比 second.second(日)
所以你 sort(ans.begin(), ans.end()) 就会自动按年月日排好
格式化输出
要会什么?
输出成 yyyy-mm-dd,月日补 0:
printf("%d-%02d-%02d\n", y, m, d);
要记住什么?
%02d:宽度 2,不够左侧补 0
3 会输出成 03
完整代码
cpp
#include <bits/stdc++.h>
using namespace std;
int fullYear(int yy) { // 00-59 -> 2000-2059, 60-99 -> 1960-1999
return (yy <= 59) ? (2000 + yy) : (1900 + yy);
}
bool isLeap(int y) {
return (y % 400 == 0) || (y % 4 == 0 && y % 100 != 0);
}
bool valid(int y, int m, int d) {
if (y < 1960 || y > 2059) return false;
if (m < 1 || m > 12) return false;
static int md[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int days = md[m] + (m == 2 && isLeap(y));
return d >= 1 && d <= days;
}
int main() {
int a, b, c;
scanf("%d/%d/%d", &a, &b, &c);
vector<pair<int, pair<int,int> > > ans; // (y, (m, d))
int y1 = fullYear(a), m1 = b, d1 = c; // yy/mm/dd
int y2 = fullYear(c), m2 = a, d2 = b; // mm/dd/yy
int y3 = fullYear(c), m3 = b, d3 = a; // dd/mm/yy
if (valid(y1,m1,d1)) ans.push_back(make_pair(y1, make_pair(m1,d1)));
if (valid(y2,m2,d2)) ans.push_back(make_pair(y2, make_pair(m2,d2)));
if (valid(y3,m3,d3)) ans.push_back(make_pair(y3, make_pair(m3,d3)));
sort(ans.begin(), ans.end());
ans.erase(unique(ans.begin(), ans.end()), ans.end());
for (int i = 0; i < ans.size(); ++i) {
int y = ans[i].first;
int m = ans[i].second.first;
int d = ans[i].second.second;
printf("%d-%02d-%02d\n", y, m, d);
}
return 0;
}