乐趣区

日期类问题

日期类问题
@(算法)
日期类问题中最基本的问题——求两个日期间的天数差。解决这类区间问题有一个统一的思想——把原区间问题统一到起点确定的区间问题上去。
日期类问题有一个特别需要注意的要点——闰年闰年的判断规则:当年数不能被 100 整除时若能被 4 整除,或者其能被 400 整除时也是闰年。用逻辑表达式为:Year%100!=0 && Year%4==0 || Year%400==0

例题
题目描述
We now use the Gregorian style of dating in Russia. The leap years are years with number divisible by 4 but not divisible by 100, or divisible by 400.For example, years 2004, 2180 and 2400 are leap. Years 2004, 2181 and 2300 are not leap.Your task is to write a program which will compute the day of week corresponding to a given date in the nearest past or in the future using today’s agreement about dating.
输入
There is one single line contains the day number d, month name M and year number y(1000≤y≤3000). The month name is the corresponding English name starting from the capital letter.
输出
Output a single line with the English name of the day of week corresponding to the date, starting from the capital letter. All other letters must be in lower case.
样例输入
9 October 2001 14 October 2001
样例输入
TuesdaySunday
代码块
// task.cpp : 定义控制台应用程序的入口点。
//

#include “stdafx.h”
#include <iostream>
#include <cstdio>
#include <cstdlib>
#define ISYEAR(x) x%100!=0 && x%4==0 || x%400==0?1:0
// 判断是否是闰年
using namespace std;

// 每月的天数
int dayOfMonth[13][2] = {
0,0,
31,31,
28,29,
31,31,
30,30,
31,31,
30,30,
31,31,
31,31,
30,30,
31,31,
30,30,
31,31
};

struct Date {
int Year;
int Month;
int Day;
void nextDay() { // 计算下一天的日期
Day++;
if (Day > dayOfMonth[Month][ISYEAR(Year)]) {
Day = 1;
Month++;
if (Month > 12) {
Year++;
Month = 1;
}

}
}
};

// 每个月的名称
char monthName[13][20] = {
“”,
“January”,
“February”,
“March”,
“April”,
“May”,
“June”,
“July”,
“August”,
“September”,
“October”,
“November”,
“December”
};

// 每天的名称
char weekName[7][20] = {
“Sunday”,
“Monday”,
“Tuesday”,
“Wednesday”,
“Thursday”,
“Friday”,
“Saturday”
};

int buf[3001][13][32];
int main()
{
Date date;
int t = 0;
date.Year = 0;
date.Month = 1;
date.Day = 1;
while (date.Year != 3001) {
buf[date.Year][date.Month][date.Day] = t;
date.nextDay();
t++;
}

int d, m, y;
char s[20];
while (scanf(“%d%s%d”, &d, s, &y) != EOF)
{
for (m = 1; m <= 12; m++) {
if (strcmp(s, monthName[m])==0) {// 将输入字符串与月名比较得出月数
break;
}
}
int days = buf[y][m][d] – buf[2019][2][26];
days += 2; // 今天是 2019.02.26,星期二,故 days+2
puts(weekName[(days % 7 + 7) % 7]); // 用 7 对其取模,并且保证其为非负数
}
return 0;
}

总结
1. 善用结构体 2. 判断闰年:#define ISYEAR(x) x%100!=0 && x%4==0 || x%400==0?1:03. 循环 nextDay(),将日期转换成 int 整型,把原区间问题统一到起点确定的区间问题上去。
int days = buf[y][m][d] – buf[2019][2][26];
days += 2; // 今天是 2019.02.26,星期二,故 days+2
puts(weekName[(days % 7 + 7) % 7]); // 用 7 对其取模,并且保证其为非负数
关键代码!int days = buf[y][m][d] – buf[2019][2][26] 可能为负数;days % 7 + 7) % 7 用 7 对其取模,保证其为非负数。
参考资料: 计算机考研——机试指南 [电子工业出版社]

退出移动版