1. 程式人生 > >演算法提高 日期計算 藍橋杯 詳解

演算法提高 日期計算 藍橋杯 詳解

演算法提高 日期計算   時間限制:1.0s   記憶體限制:256.0MB 問題描述   已知2011年11月11日是星期五,問YYYY年MM月DD日是星期幾?注意考慮閏年的情況。尤其是逢百年不閏,逢400年閏的情況。 輸入格式   輸入只有一行
  YYYY MM DD
輸出格式   輸出只有一行
  W
資料規模和約定   1599 <= YYYY <= 2999
  1 <= MM <= 12
  1 <= DD <= 31,且確保測試樣例中YYYY年MM月DD日是一個合理日期
  1 <= W <= 7,分別代表週一到週日
樣例輸入 2011 11 11 樣例輸出 5

我一直對這種日期計算計算的題目存在恐懼感,因為這類題目普遍不難,但是多一天少一天的問題搞得我頭都大了,好在今天仔細在紙上畫了一下,想出了一種比較通用的做法,如有雷同,純屬你抄我大笑開玩笑,但我還是要好好整理一下解題思路

1.閏年問題:當然是通過函式判斷閏年,我想如果不是萬年一見的水題,一般計算日期時間都是要考慮閏年的。閏年的兩種情況:1.能被4整除但不能被100整除;2.能被400整除,也就是常說的四年一閏,百年不閏,四百年再閏

2.天數問題:這裡題目一般都會給出一個基礎日期的資訊,但是相信我,最好是花點時間算出某一年1月1號的資訊,因為這會讓思路變得很清晰,如果你算不出來,也有一個投機取巧的方法(假如條件允許),電腦下面的時間可以給你提供很全面正確的資訊,有了基礎天數後,以本題為例,2011年1月1日是星期6。

首先算年份差所帶來的天數差

(1)給出的年份比基礎年份小或者就是2011年,比如2009年,我們首先計算2009年1月1日到2011年1月1日的天數,相信這個應該難不倒你吧,閏年366天,非閏年365天,2009年開始,算完2010年結束。

(2)給出的年份比基礎年份大,比如2013年,當然就是從2011年開始,算完2012年結束

經過這個步驟,得到day1

然後算由於月份和天的差所帶來的天數差

(1)首先當然是計算1月1日到給定的日期(比如3月8號)的天數,計算的時候是用迴圈,從1月開始加,加完2月結束,最後再加上8天,但是注意,你此時算出的天數多了1,舉個例子,1月1日到1月3日有幾天?當然是2天,這要比3多1天,因為起始點就是1了,明白了這個,我們就可以用得出的天數減1,從而獲得了第二個天數day2

關鍵時刻,計算真實的天數差

(1)如果給出的年份小於等於基礎年份,那麼我們得到的day1實際上是算多了,而且正好多出了day2天,所以真正的天數差是day1-day2

(2)如果給出的年份大於基礎年份,那麼天數實際上是算少了,少了day2天,所以真正的天數是day1+day2

在得出天數之後,我們還要分情況,首先將得到的天數差day%7,得到星期差

(1)如果給出的年份小於等於基礎年份,那麼應該從基礎時間(星期六)向負方向數day%7天,注意1之後要變成7

(2)如果給出的年份大於基礎年份,那麼應該從基礎時間(星期六)向正方向數day%7天,注意7之後要變成1

最終我們就得到了正確的星期

#include<iostream>
#include<cmath>
using namespace std;

bool leap(int year)
{
	if(year%4==0&&year%100!=0)
	return true;
	if(year%400==0)
	return true;
	return false;
} 

int getYD(int year)
{
	int sum=0;
	int i;
	if(year<=2011)
	{
		for(i=year;i<2011;i++)
		{
			if(leap(i))
			sum+=366;
			else
			sum+=365;	
		}
	}
	if(year>2011)
	{
		for(i=2011;i<year;i++)
		{
			if(leap(i))
			sum+=366;
			else
			sum+=365;
		}
	}
	return sum;
}

int getMD(int year,int mon,int day)
{
	int i;
	int sum=0;
	for(i=1;i<mon;i++)
	{
		if(i==1||i==3||i==5||i==7||i==8||i==10||i==12)
		sum+=31;
		if(i==4||i==6||i==9||i==11)
		sum+=30;
		if(i==2&&leap(year))
		sum+=29;
		if(i==2&&!leap(year))
		sum+=28;
	}
	sum=sum+day-1;
	return sum;
}



int main()
{
	int year,mon,day,sum;
	while(cin>>year>>mon>>day)
	{
		sum=getYD(year);
		//cout<<getMD(year,mon,day)<<endl;;
		if(year<2011)
		{
			sum=sum-getMD(year,mon,day);
			//cout<<sum<<endl;
			cout<<(sum%7==6?7:abs(6-(sum%7)))<<endl;
		}
		else
		{
			sum=sum+getMD(year,mon,day);
			//cout<<sum<<endl;
			cout<<((6+(sum%7))>7?((6+(sum%7))%7):(6+(sum%7)))<<endl;
		}
		
		
	}
	return 0;
}