• 机考指南第二章-经典入门-日期问题自解


    日期类问题:

    1.基本问题:

    求两个日期间的天数差,即求以两个特定日期为界的日期区间的长度。

    2.套路:

    将原区间问题统一到起点确定的区间问题上去(比如与0000年1月1日的日期之差)。这样处理可以对数据进行预处理,在输入之前就预处理出所有日期与原点日期之间的天数差保存起来,当数据真正开始输入时,只需O(1)的时间复杂度将保存的数据读出即可,是一种空间换时间的重要手段。

    3.注意的要点——闰年:

    每逢闰年2月将会有29天。闰年的判定——当年数不能被100整除时若其能被4整除则为闰年,或者其能被400整除也是闰年。即Year%100!=0&&Year%4==0||Year%400==0。

    例2.3 日期差值

    AC代码:

    #include<cstdio>
    using namespace std;
    
    bool LeapYear(int x)
    {
        return (x % 100 != 0 && x % 4 == 0) || x % 400 == 0;
    }
    
    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 Day;
        int Month;
        int Year;
        void NextDay()//计算下一天的日期
        {
            Day++;
            if (Day > dayOfMonth[Month][LeapYear(Year)])
            {
                Day = 1;
                Month++;
                if (Month > 12)
                {
                    Month = 1;
                    Year++;
                }
            }
        }
    };
    
    int days[5001][13][32];//保存将要处理的天数
    
    int Abs(int x)//求绝对值
    {
        return x < 0 ? -x : x;
    }
    
    int main()
    {
        Date tmp;
        int cnt = 0;
        tmp.Day = 1;
        tmp.Month = 1;
        tmp.Year = 0;//初始化对象为0000年1月1日
        while (tmp.Year != 5001)//预处理
        {
            days[tmp.Year][tmp.Month][tmp.Day] = cnt;//将该日与0000年1月1日的天数差保存起来
            tmp.NextDay();//计算下一天的日期
            cnt++;//计数器累加,每经过一天计数器加1,表示与原点日期间隔又增加一天
        }
        int d1, m1, y1, d2, m2, y2;
        while (scanf("%4d%2d%2d", &y1, &m1, &d1) != EOF)
        {
            scanf("%4d%2d%2d", &y2, &m2, &d2);
            printf("%d
    ", Abs(days[y2][m2][d2] - days[y1][m1][d1] + 1));
        }
        return 0;
    }
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    int month[13][2] = { 0, 0, 31,31,29,28,31,31,30,30,31,31,30,30,31,31,31,31,30,30,31,31,30,30,31,31 };
    
    bool isLeapYear(int x)
    {
        return (x % 4 && !(x % 100)) || (x % 400);
    }
    
    int main()
    {
        int y1, m1, d1, y2, m2, d2;
        int cnt = 1;
        while (scanf("%4d%2d%2d", &y1, &m1, &d1) != EOF && scanf("%4d%2d%2d", &y2, &m2, &d2) != EOF)
        {
            while (y1 != y2 || m1 != m2 || d1 != d2)
            {
                d1++;
                cnt++;
                if (d1 > month[m1][isLeapYear(y1)])
                {
                    d1 = 1;
                    m1++;
                    if (m1 > 12)
                    {
                        m1 = 1;
                        y1++;
                    }
                }
            }
            printf("%d
    ", cnt);
        }
        //system("pause");
        return 0;
    }
    二刷
    #include<cstdio>
    using namespace std;
    
    int month[13][2] = { 0,0,31,31,29,28,31,31,30,30,31,31,30,30,31,31,31,31,30,30,31,31,30,30,31,31 };
    
    bool isLeapYear(int x)
    {
        return (x % 4 && !(x % 100)) || x % 400;
    }
    
    int count(int y1, int m1, int d1)
    {
        int y = 0, m = 1, d = 1, c = 0;
        while (y != y1 || m != m1 || d != d1)
        {
            d++;
            c++;
            if (d > month[m][isLeapYear(y)])
            {
                d = 1;
                m++;
                if (m > 12)
                {
                    m = 1;
                    y++;
                }
            }
        }
        return c;
    }
    
    int main()
    {
        int y1, d1, m1;
        int y2, d2, m2;
        while (scanf("%04d%02d%02d", &y1, &m1, &d1) != EOF && scanf("%04d%02d%02d", &y2, &m2, &d2)!=EOF)
        {
            int a = count(y1, m1, d1);
            int b = count(y2, m2, d2);
            int ans;
            if (a > b)ans = a - b;
            else ans = b - a;
            printf("%d
    ", ans + 1);
        }
        return 0;
    }
    三刷

    例2.4 Day of Week

    AC代码:

    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    bool LeapYear(int x)
    {
        return (x % 100 != 0 && x % 4 == 0) || x % 400 == 0;
    }
    
    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 };
    char WeekName[7][20] = { "Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday" };
    char MonthName[13][20] = { "", "January","February","March","April","May","June","July","August","September","October","November","December" };
    
    struct Date
    {
        int Day;
        int Month;
        int Year;
        void NextDay()//计算下一天的日期
        {
            Day++;
            if (Day > dayOfMonth[Month][LeapYear(Year)])
            {
                Day = 1;
                Month++;
                if (Month > 12)
                {
                    Month = 1;
                    Year++;
                }
            }
        }
    };
    
    int days[5001][13][32];//保存将要处理的天数
    
    int Abs(int x)//求绝对值
    {
        return x < 0 ? -x : x;
    }
    
    int main()
    {
        Date tmp;
        int cnt = 0;
        tmp.Day = 1;
        tmp.Month = 1;
        tmp.Year = 0;//初始化对象为0000年1月1日
        while (tmp.Year != 5001)//预处理
        {
            days[tmp.Year][tmp.Month][tmp.Day] = cnt;//将该日与0000年1月1日的天数差保存起来
            tmp.NextDay();//计算下一天的日期
            cnt++;//计数器累加,每经过一天计数器加1,表示与原点日期间隔又增加一天
        }
        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 index = days[y][m][d] - days[2019][6][10];//比较对象为2019年6月10日,周一
            printf("%s
    ", WeekName[(index % 7 + 7) % 7]);//处理复数情况
        }
        return 0;
    }
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int month[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 };
    char Month[13][20] = { " ","January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
    char Days[7][20] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday","Sunday" };
    bool isLeapYear(int x)
    {
        return (x % 4 == 0 && x % 100 != 0) || x % 400 == 0;
    }
    
    int count(int y1, int m1, int d1)
    {
        int y = 1, m = 1, d = 1, c = 0;
        while (y != y1 || m != m1 || d != d1)
        {
            d++;
            c++;
            if (d > month[m][isLeapYear(y)])
            {
                d = 1;
                m++;
                if (m > 12)
                {
                    m = 1;
                    y++;
                }
            }
        }
        return c;
    }
    
    int main()
    {
        int y1, d1, m1;
        char m[20];
        while (scanf("%d%s%d", &d1, m, &y1) != EOF)
        {
            for (int i = 1; i < 13; i++)
            {
                if (strcmp(m, Month[i]) == 0)
                {
                    m1 = i;
                    break;
                }
            }
            int cnt = count(y1, m1, d1);
            int ans = cnt % 7;
            printf("%s
    ", Days[ans]);
        }
        return 0;
    }
    二刷

    注意闰年判断不能使用如下语句:

    return (x % 4 && !x % 100) || x % 400;

    因为“或”是用于肯定思路的,如图中x=4是就会导致错误判断,因为0||1=1。

  • 相关阅读:
    一,安装python
    maven搭建ssm
    web优化
    java代码优化29个点
    供参考的 php 学习路线
    javascript-文档结构遍历
    jquery中的cookie使用
    jQuery中的Ajax
    lambda和抽象类
    上传jar包到nexus私服
  • 原文地址:https://www.cnblogs.com/yun-an/p/11028183.html
Copyright © 2020-2023  润新知