日期问题
小明正在整理一批历史文献。这些历史文献中出现了很多日期。
小明知道这些日期都在1960年1月1日至2059年12月31日。
令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。
更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。
比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。
给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?
输入格式
一个日期,格式是”AA/BB/CC”。
即每个’/’隔开的部分由两个 0-9 之间的数字(不一定相同)组成。
输出格式
输出若干个不相同的日期,每个日期一行,格式是”yyyy-MM-dd”。
多个日期按从早到晚排列。
数据范围
0≤A,B,C≤9
输入样例:
02/03/04
输出样例:
2002-03-04
2004-02-03
2004-03-02
思路:原先我的思路就是模拟整个过程,写入,合法判断,从小到大排序,去重,输出,写了150多行代码后AC75%。
代码如下:
using namespace std;
bool leagal(int year, int month, int day)
{
if (month <= 0 || day <= 0)
{
return false;
}
int date[2][12] = { {31,28,31,30,31,30,31,31,30,31,30,31},{31,29,31,30,31,30,31,31,30,31,30,31} };
if ((year % 4 && year % 100 != 0) && month <= 12 && day <= 31|| year % 400 == 0 )
{
if (date[1][month - 1] >= day)
{
return true;
}
else
{
return false;
}
}
else if(month <= 12 && day <= 31)
{
if (date[0][month - 1] >= day)
{
return true;
}
else
{
return false;
}
}
return false;
}
int main()
{
int x1, x2, x3, N = 0;
int arr[3][3] = { 0 };
scanf_s("%d/%d/%d", &x1, &x2, &x3);
int t1 = x1, t2 = x2, t3 = x3;
if (t1 < 100)
{
if (t1 < 60)t1 += 2000;
else t1 += 1900;
if (leagal(t1, t2, t3))
{
arr[N][0] = t1;
arr[N][1] = t2;
arr[N][2] = t3;
N++;
}
}
t1 = x1, t2 = x2, t3 = x3;
if (t3 < 100)
{
if (t3 < 60)t3 += 2000;
else t3 += 1900;
if (leagal(t3, t1, t2))
{
arr[N][0] = t3;
arr[N][1] = t1;
arr[N][2] = t2;
N++;
}
if (leagal(t3, t2, t1))
{
arr[N][0] = t3;
arr[N][1] = t2;
arr[N][2] = t1;
N++;
}
}
int min_year = arr[0][0], min_month = arr[0][1], min_day = arr[0][2];
for (int i = 0; i < N - 1; i++)
{
for (int j = 0; j < N - i - 1; j++)
{
if (arr[j][0] > arr[j + 1][0])
{
int t = arr[j][0];
arr[j][0] = arr[j + 1][0];
arr[j + 1][0] = t;
t = arr[j][1];
arr[j][1] = arr[j + 1][1];
arr[j + 1][1] = t;
t = arr[j][2];
arr[j][2] = arr[j + 1][2];
arr[j + 1][2] = t;
}
else if (arr[j][0] == arr[j + 1][0] && arr[j][1] > arr[j + 1][1])
{
int t = arr[j][0];
arr[j][0] = arr[j + 1][0];
arr[j + 1][0] = t;
t = arr[j][1];
arr[j][1] = arr[j + 1][1];
arr[j + 1][1] = t;
t = arr[j][2];
arr[j][2] = arr[j + 1][2];
arr[j + 1][2] = t;
}
else if (arr[j][0] == arr[j + 1][0] && arr[j][1] == arr[j + 1][1] && arr[j][1] > arr[j + 1][1])
{
int t = arr[j][0];
arr[j][0] = arr[j + 1][0];
arr[j + 1][0] = t;
t = arr[j][1];
arr[j][1] = arr[j + 1][1];
arr[j + 1][1] = t;
t = arr[j][2];
arr[j][2] = arr[j + 1][2];
arr[j + 1][2] = t;
}
}
}
for (int i = 0; i < N; i++)
{
if (arr[i][0] == arr[i + 1][0] && arr[i][1] == arr[i + 1][1] && arr[i][2] == arr[i + 1][2])
{
for (int j = i + 1; j < N - 1; j++)
{
arr[j][0] = arr[j + 1][0];
arr[j][1] = arr[j + 1][1];
arr[j][2] = arr[j + 1][2];
}
N--;
}
}
for (int i = 0; i < N; i++)
{
cout << arr[i][0] << "-";
if (arr[i][1] < 10)
{
cout << 0 << arr[i][1] << "-";
}
else
{
cout << arr[i][1] << "-";
}
if (arr[i][2] < 10)
{
cout << 0 << arr[i][2] << endl;
}
else
{
cout << arr[i][2] << endl;
}
}
return 0;
}
后来参考了网上的一种写法,发现十分之妙。
思路:从1960年1月1日至2059年12月31日看做数字,逐个遍历,即遍历(19600101~20591231)这么多数,遍历时判断合法与是否是输入。
注意输出:例如输出1960-01-01,应使用
printf("%02d-%02d-%02d",year,month,day);//其中%02d意思是不足2位高位补0
代码如下:
using namespace std;
int mon[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
bool check(int year,int month,int day)
{
if (month == 0 || day == 0)return false;
if (month > 12 || day > 31)return false;
if (month == 2)
{
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
{
if (day > 29)return false;
}
else
{
if (day > 28)return false;
}
}
else
{
if (day > mon[month])return false;
}
return true;
}
int main()
{
int a, b, c;
scanf_s("%d/%d/%d", &a, &b, &c);
for (int i = 19600101; i <= 20591231; i++)
{
int year = i / 10000;
int month = i % 10000 / 100;
int day = i % 100;
if (check(year,month,day))
{
if ((year % 100 == a && month == b && day == c) || (year % 100 == c && month == b && day == a) || (year % 100 == c && month == a && day == b))
{
printf("%02d-%02d-%02d\n", year, month, day);
}
}
}
return 0;
}