Codeup 1928 日期差值

题目描述

Codeup 1928 日期差值

时间限制 1 Sec 内存限制 32 MB

题目描述

有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天。

输入

有多组数据,每组数据有两行,分别表示两个日期,形式为YYYYMMDD

输出

每组数据输出一行,即日期差值

样例输入

20130101
20130105

样例输出

5

思路分析

这个题目乍一看很不好处理,因为涉及年份月份会有闰年,二月和大小月份之分,凭借计算机根据月份名称去判断一个月份的天数不是很好实现,特别是对于二月份,于是用数组直接存放平年或者闰年的每个月的天数不失为是一种使用一定存储空间来实现解决日期问题的简单办法。

用二维数组存储不同性质年份的每个月的天数,直观,简单,数组下表第一维与月份对应,第二维则表示平年或者闰年如:

  mouth[2][0]	表示平年的二月份
  mouth[2][1]	表示闰年的二月份

呼应简单模拟的章节目录名,求日期差值的最简单的方式就是令小的那一个日期不断地+1,直到与较大的日期相等时为止即可统计出答案。期间要注意的是当天数d等于当前月份所拥有的天数+1时,需要将月份m+1并且重置d为1,对于年份也是如此,m等于13时,要讲年份y+1并将m置为1。

根据题目描述的具体思路就是:

  • step 1,设立数组存放不同性质年份的每个月份的天数;
  • step 2,编写函数判断某年份是否为闰年,是则返回1,不是则返回0,对应数组的第二维下表,0表示的平年,1表示的闰年;
  • step 3,输入两个时间,比较两个时间的大小,保证t2大于t1,若t1大于t2则交换二者的值,方便后续在假设t2大于t1的情况下统一对数据进行处理,得出时间差值。
  • step 4,对输入的YYYYMMDD格式日期进行分割,分别给出表示年份,月份和天数的变量y,m,d;
  • step 5,根据简单模拟的原则在第一个日期没能达到第二个日期的时候(即,y1 < y2 || m1 < m2 || d1 < d2的时候)循环将第一个日期不断+1,期间注意月份和年份变化;
  • step 6,用变量ans(因为两个日期是连续的我们规定他们之间的天数为两天故ans初始值为1)统计循环次数即日期差值并打印输出。

Code one和Code two的差别在于对年份的处理,Code one将年份作为最大的单位按照一天一天进行模拟,这是一笔很大的计算量,为了提高速度,Code two将计算量最大的年份独立出来处理,只对最后一年进行一天天的模拟,在测试数据年份相差较多时,会有明显更加优秀的表现。

AC代码:

Code one:

#include<stdio.h>

int mouth[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}};
    //用数组存储每个月的天数,直观,简单
    //数组mouth[0][0]赋值为{0,0},方便下标与月份对应
bool isLeap(int year)
{   //判断是否为闰年
    //即,能被4整除并且不能被100整除的年份是闰年,能被400整除的也是闰年
    return(year % 4 ==0 && year % 100 != 0) || (year % 400 == 0);
}

int main()
{
    int t1,t2;
    int y1,y2,m1,m2,d1,d2;

    while(scanf("%d%d",&t1,&t2) != EOF){
        if(t1 > t2){
            //t1如果大于t2 则交换t1 t2
            int temp;
            temp = t1;
            t1 = t2;
            t2 = temp;
        }

        y1 = t1 / 10000;
        y2 = t2 / 10000;
        m1 = t1 % 10000 /100;
        m2 = t2 % 10000 /100;
        d1 = t1 % 100;
        d2 = t2 % 100;
        int ans = 1;
        //ans用于记录差值
        while(y1 < y2 || m1 < m2 || d1 < d2){
                //令日期不断+1,使得最终t1能与t2一致,统计+1次数即日期插值
            d1++;
            if(d1 == mouth[m1][isLeap(y1)] + 1){
                m1++;
                d1 = 1;
            }
            if(m1 == 13){
                y1++;
                m1 = 1;
            }
            ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}

Code two:

#include<cstdio>

int mouth[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}};

bool isLeap(int year)
{  
    return(year % 4 ==0 && year % 100 != 0) || (year % 400 == 0);
}

int main()
{
    int t1,t2;
    int y1,y2,m1,m2,d1,d2;
    int temp;
    while(scanf("%d%d",&t1,&t2) != EOF){
        if(t1 > t2){
            temp = t1;
            t1 = t2;
            t2 = temp;
        }

        y1 = t1 / 10000;
        y2 = t2 / 10000;
        m1 = t1 % 10000 /100;
        m2 = t2 % 10000 /100;
        d1 = t1 % 100;
        d2 = t2 % 100;
        int ans = 1;
        while(y1 < y2 - 1){
            if(isLeap(y1)&&m1<3)
                ans++;
            y1++;
            ans += 365;
        }
      //直接对年份进行操作,把第一个日期的年份不断+1直到与第二个年份相差1
      //期间是闰年在ans上加1再加365,不是闰年直接加365
      //相比较于Code one在年份差距较大的数据输入时可以显著加快运算速度
        while(y1 < y2 ||m1 < m2 || d1 < d2){
            d1++;
            if(d1 == mouth[m1][isLeap(y1)] + 1){
                m1++;
                d1 = 1;
            }
            if(m1 == 13){
                y1++;
                m1 = 1;
            }
            ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值