【日期类问题】例2.2 Day of week

二 日期类问题

此类问题解题思路: 定一个锚点日期,如0年1月1日,先算出往后多少年内每一日子距离这个锚点的天数,例如要算两个日期间天数时,便可以将两个日期距离锚点日期之间的天数相减,即可得到。

题目描述:
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
样例输出:
Tuesday
Sunday
来源:
2008年上海交通大学计算机研究生机试真题

该题大意: 给出输入一个日期,要求输出该日期为星期几。(给出今天的日期,以及今天的星期)
解题思路: 星期几是以七为周期循环的,用今天的星期,加上今天与给定日子的间隔天数(间隔天数注意正负情况),对7求余,即可。

#include<bits/stdc++.h>
#define ISYEAP(x) x%100!=0 && x%4==0 || x%400==0 ? 1:0 
using namespace std;

int Day[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 d; // day
	int m; // mouth 
	int y; // year
	void nextDay(){
		d++;
		if(d>Day[m][ISYEAP(y)]){
			d = 1;
			m++;
			if(m>12){
				m = 1;
				y++;
			}
		}
	} 
};
int buf[5001][13][32];
int abs(int x){
	return x < 0 ? -x:x;
}
char monthName[13][20] = {
    "",
    "January",
    "February",
    "March",
    "April",
    "May",
    "June",
    "July",
    "August",
    "September",
    "October",
    "November",
    "December"
};//月名 每个月名对应下标1到12 
char weekName[7][20] = {
	"Sunday",
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday"
};//周名 每个周名对应下标0到6 

int main()
{
	Date tmp;
	int cnt = 0;
	tmp.d = 1;
	tmp.m = 1;
	tmp.y = 0;
	while(tmp.y < 5001){
		buf[tmp.y][tmp.m][tmp.d] = cnt;
		tmp.nextDay();
		cnt++;
	} //预处理每一天与锚点日期的天数差 
	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[2012][7][16];//计算给定日期与今天日期的间隔天数(注意可能为负) 
        days+=1;//今天(2012.7.16) 为星期一,对应的数组下标为1,则计算1经过days天后的下标 
        puts(weekName[(days % 7 + 7) % 7]);//将计算后得出的下标用7对其取模,并保证其为非负数,则该下标即为答案所对应的下标,输出即可 
	}
	return 0;
}

注意: 大数组定义,一律定义为全局变量,定义在函数内容易发生爆栈。

其他方法:

蔡勒(Zeller)公式来解决,随便给一个日期,就能用这个公式推算出是星期几。
以1582年10月4日为例:
1582年10月4日后:w = (d + 1+ 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400 ) % 7;
1582年10月4日前:w = (d +1 + 2*m + 3*(m+1)/5 + y + y/4 + 5 ) % 7;
以1752年9月3日为例:
1752年9月3日后:w = (d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400 ) % 7;
1752年9月3日前:w = (d + 2*m + 3*(m+1)/5 + y + y/4 + 5 ) % 7;

猜你喜欢

转载自blog.csdn.net/zdx1996/article/details/86561314