日期類問題

日期類問題

@(算法)

日期類問題中最基本的問題——求兩個日期間的天數差。
解決這類區間問題有一個統一的思想——把原區間問題統一到起點確定的區間問題上去

日期類問題有一個特別需要注意的要點——閏年
閏年的判斷規則:當年數不能被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

樣例輸入

Tuesday
Sunday

代碼塊

// 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:0
3.循環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對其取模,保證其爲非負數。

參考資料:計算機考研——機試指南[電子工業出版社]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章