算法09 模拟算法之日期模拟

日期模拟

无论是中小学编程竞赛还是大学生编程竞赛,日期模拟都是经常会出现的题目。

日期模拟经常会出现以下题型:

  • 得到某年某月的天数
  • 判断给定日期的合法性
  • 给定年份,求这一年第n天的日期
  • 给定年月日,求经过n天后的日期
  • 查找两个日期之间有多少个回文日期... ...

 

得到某年某月的天数

得到某年某月的天数问题经常会作为其他问题的模板来使用。

首先我们需要存储一年中所有月份相对应的天数

int day[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}

其中day[1]表示一月份最多31天,2月份先赋值为28天,具体天数还需要检测年份是否是闰年,如果是闰年还需要+1天

闰年分为两种:

普通闰年:年份是4的倍数,但不是100的倍数,例如2004、2020年等

世纪闰年:是400的倍数,例如1900不是世纪闰年,2000是世纪闰年,即:

if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
    是闰年;
else
    不是;

得到某年某月的天数

当月份不是2月时,就返回指定当前月份初始天数

当月份是2月时,判断年份是否是闰年,当年份为闰年成立时,leap值为1,不成立时值为0,初始天数加上leap的值即为2月份天数

int days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// 得到某年某月的天数
int check(int y, int m)
{
    if(m != 2) return days[m];
    else
    {
        //特判 2 月
        int leap = (y % 4 == 0 && y % 100 != 0 || y % 400 == 0);
        return days[m] + leap;
    }
}

 

判断日期的合法性

一般这样的题型会先给你一个格式,看是否符合这个格式,比如要满足20230701这样的格式才是合法的。

首先你需要分离出年份,再分离出月份,最后分离出日。

再分别判断年月日是否符合题意

if(m<1||m>12) 则月份不符合
if(d<1||d>(指定月份的总天数)) 则日不符合

注:年份一般不需要检查,但也要视题意而定

 

训练:第n天的日期

给定一个年份y和一个整数d,问这一年的第d天是几月几日?注意闰年的2月有29天。满足下面条件之一的是闰年:

1、年份是4的整数倍,而且不是100的整数倍;

2、年份是400的整数倍。

【输入描述】输入的第一行包含一个整数y,表示年份,年份在1900到2015之间(包含1900和2015)。

输入的第二行包含一个整数d,d在1至365之间。

【输出描述】输出两行,每行一个整数,分别表示答案的月份和日期。

【样例输入1】

2015

80

【样例输出】

3

21

 

第n天的日期参考代码

#include <iostream>
using namespace std;
int day[13]={0,31,0,31,30,31,30,31,31,30,31,30,31};
bool check(int n)  //判断闰年
{
    if(n%400==0||(n%4==0&&n%100!=0))  return true;
    return false;
}

int main()
{
    int m,n;
    cin>>m>>n;
    if(check(m))  day[2]=29;
    else  day[2]=28;
    for(int j=1;j<=12;j++)
    {
        n-=day[j];
        if(n<0){
            cout<<j<<endl<<day[j]+n;
            break;
        }
        if(n==0){
            cout<<j<<endl<<day[j];
            break;
        }
    }
    return 0;
}

 

训练:日期距离

输入一个的日期,输出它和2014年5月17日相差有多少天?注意闰年的2月有29天。满足下面条件之一的是闰年:

1、年份是4的整数倍,而且不是100的整数倍;

2、年份是400的整数倍。

【输入描述】输入的第一行包含一个整数y,表示年份,年份在1到2014之间(包含1和2014)。

输入的第二行包含一个整数m,表示月份,m在1至12之间。

输入的第三行包含一个正整数d,表示日期,d在1至31之间。

【输出描述】输出两个日期之间相差的天数。

【输入样例】

1988

7

3

【输出样例】

9449

 

日期距离参考代码

#include <iostream>
using namespace std;
int day[13]={0,31,0,31,30,31,30,31,31,30,31,30,31};
bool check(int k)  //判断闰年
{
    if(k%400==0||(k%4==0&&k%100!=0))
        return true;
    return false;
}
int sum;//计算总天数
int main()
{
    int m,n,d;
    cin>>m>>n>>d;
    if(check(m))  day[2]=29;
    else  day[2]=28;
    for(int i=m+1;i<2014;i++)  //计算完整的年份天数
    {
        if(check(i))  sum+=366;
        else sum+=365;
    }
    if(m==2014)
    {
        for(int i=n+1;i<5;i++) //计算完整的月份的天数
        sum+=day[i];
        if(n==5) sum+=17-d;
        else sum+=day[n]-d+17;
    }
    else
    {
        sum+=137; //2014.1.1~2014.5.17总天数
        for(int i=n+1;i<=12;i++)   //算上完整月份天数
            sum+=day[i];
        sum+=day[n]-d;   
    }
    cout<<sum<<endl;
    return 0;
}