这道题,我做复杂了。而且自己的做法要判断的情况太多,一个不小心就会有所遗漏。虽然后来补全了一些遗漏的情况,但提交老是WA,应该是还有什么情况漏掉了。总之,自己这种做法太过笨拙,而且吃力不讨好。
后来我看到有一种思路,不用具体判断闰年,因为题目本身只是要给出有多少个而已,这样的解法比我自己的解法巧妙多了,而且短短几行coding就可以解决。具体资格赛完了之后再改一下博客贴出来。
先贴个自己写的一直WA显然遗漏什么情况的版本,也以示警戒吧。还是得多加修炼才行啊。
题目1 : 2月29日
-
4 January 12, 2012 March 19, 2012 August 12, 2899 August 12, 2901 August 12, 2000 August 12, 2005 February 29, 2004 February 29, 2012
样例输出
-
Case #1: 1 Case #2: 0 Case #3: 1 Case #4: 3
描述
给定两个日期,计算这两个日期之间有多少个2月29日(包括起始日期)。
只有闰年有2月29日,满足以下一个条件的年份为闰年:
1. 年份能被4整除但不能被100整除
2. 年份能被400整除
输入
第一行为一个整数T,表示数据组数。
之后每组数据包含两行。每一行格式为"month day, year",表示一个日期。month为{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November" , "December"}中的一个字符串。day与year为两个数字。
数据保证给定的日期合法且第一个日期早于或等于第二个日期。
输出
对于每组数据输出一行,形如"Case #X: Y"。X为数据组数,从1开始,Y为答案。
数据范围
1 ≤ T ≤ 550
小数据:
2000 ≤ year ≤ 3000
大数据:
2000 ≤ year ≤ 2×109
#include<cstring>
#include<iostream>
using namespace std;
struct Month{
char* strMonth;
int nMonth;
}reserved[12] = {
{ "January", 1 }, { "February", 2 },
{ "March", 3 }, { "April", 4 },
{ "May", 5 }, { "June", 6 },
{ "July", 7 }, { "August", 8 },
{ "September", 9 }, { "October", 10 },
{ "November", 11 }, { "December", 12 }
};
struct Date{
int month;
int day;
int year;
};
bool isLeap(int y){
if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0)
return true;
else
return false;
}
//assume that the year is different,and they are both leap years
int incl_st_end(Date date1, Date date2){
int m1 = date1.month, m2 = date2.month,
d1 = date1.day, d2 = date2.day;
if (m1 <= 2 && (m2 > 2 || (m2 == 2 && d2 == 29)))
return 1;
else if (m1 > 2 && (m2 < 2 || (m2 == 2 && d2 < 29)))
return -1;
else return 0;
}
int howManyLeaps(Date date1, Date date2){
int d1 = date1.day, d2 = date2.day,
m1 = date1.month, m2 = date2.month,
y1 = date1.year, y2 = date2.year;
int cnt;
int howMany = 0;
int beginLeap = y1, endLeap = y2;
Date begin, end;
if (y1 == y2)//same year
{
if (isLeap(y1))//leap year
{
if (m1 == m2)//same month
{
if (m1 == 2){
if (d2 != 29)//one
return 0;
else//none
return 1;
}
else
return 0;
}
else //different months
{
if (m1 <= 2 && m2 > 2)
return 1;
else
return 0;
}
}
else //not Leap year
return 0;
}
else //not the same year
{
//judge if we have to include the begin year and the end year
for (; beginLeap < y2; beginLeap++){
if (isLeap(beginLeap))
break;
}
for (; endLeap > y1; endLeap--){
if (isLeap(endLeap))
break;
}
if (beginLeap>endLeap)//if no leap years
return 0;
if (beginLeap == y1&&endLeap == y2){
begin = date1;
end = date2;
}
else if (beginLeap == y1&&endLeap != y2){
end.day = 31;
end.month = 12;
end.year = endLeap;
begin = date1;
}
else if(beginLeap!=y1&&endLeap==y2){
begin.day = 1;
begin.month = 1;
begin.year = beginLeap;
end = date2;
}
else {
begin.day = 1;
begin.month = 1;
begin.year = beginLeap;
end.day = 31;
end.month = 12;
end.year = endLeap;
}
cnt = incl_st_end(begin, end);
for (int tmp(begin.year); tmp < end.year; tmp = tmp + 4){
if (isLeap(tmp))
howMany++;
}
howMany += cnt;
return howMany;
}
}
int main(){
int t,i,j,num;
char strMonth[10]="";
int month, day, year;
char delimeter;
Date d[2];
cin >> t;
for (i = 0; i < t; i++){
for (j = 0; j < 2; j++){
cin >> strMonth >> day >> delimeter >> year;
for (int i(0); i < 12; i++){
if (strcmp(strMonth, reserved[i].strMonth) == 0){
month = reserved[i].nMonth;
break;
}
}
d[j].day = day;
d[j].month = month;
d[j].year = year;
}
num = howManyLeaps(d[0], d[1]);
cout << "Case #" << i+1 << ":" << " " << num << endl;
}
}
网上看到的一种AC解法:
#include <cstdio>
#include <cstring>
int main()
{
char start_month[12], end_month[12];
int start_day, start_year, end_day, end_year;
int T, count;
while(scanf("%d", &T)!=EOF)
{
for(int i=1; i<=T; ++i)
{
scanf("%s %d, %d", start_month, &start_day, &start_year);
scanf("%s %d, %d", end_month, &end_day, &end_year);
count = 0;
if(strcmp(start_month,"January")==0 || (strcmp(start_month,"February")==0&&start_day<=29))
{
--start_year;
}
if(strcmp(end_month,"January")==0 || (strcmp(end_month,"February")==0&&end_day<29))
{
--end_year;
}
count = (end_year>>2)-(start_year>>2);
count = count -(end_year/100-start_year/100);
count += ((end_year/400-start_year/400));
printf("Case #%d: %d\n", i, count);
}
}
return 0;
}
转自这里的。