蓝桥杯-计蒜客之节假日

题干:

 日历有 阳历(公历) 和 阴历(农历) 之分。每年都有法定节假日,这些分成三类—双休、阳历节假日、阴历节假日。

  1. 双休

    1)周六和周日 2 天

  2. 阳历节假日

    1)元旦:阳历每年 1 月 1 日,放假 1 天

    2)劳动节:阳历每年 5 月 1 日,放假 1 天

    3)国庆节:阳历每年 10 月 1 日,放假 3 天

    4)圣诞节:阳历每年 12 月 25 日,放假 1 天

  3. 阴历节假日

    1)春节:阴历每年 1 月 1 日,放假 3 天

    2)清明节:阳历每年 4 月 4 - 6 日之间的某天,放假 1 天

    3)端午节:阴历每年 5 月 5 日,放假 1 天

    4)中秋节:阴历每年 8 月 15 日, 放假 1 天

 当节假日和双休重合时,双休 不延后 也 不提前,保证节假日之间不会重合。现在给你某年的所有阴历节假日的 阳历 日期,以及当年的 1 月 1 日是星期几,请你计算出这一年(阳历 1 月 1 日到 12 月 31 日)放了多少天假(包括双休、阳历节假日和阴历节假日)。

输入格式

第一行输入年份 y(1900<y2050)。

接下来 4 行,每行输入两个整数,m,d, 分别表示春节、清明节、端午节和中秋节的阳历日期。

最后一行一个整数表示当年 1 月 1 号是星期几(一周内的第几天,每周从星期一开始计数,即星期一为第一天)。

输出格式

输出一个整数,表示当年放假的天数。

样例输入

2017
1 28
4 4
5 30
10 4
7

样例输出

113

题目分析:

(1)刚开始想用蔡基姆拉尔森计算公式来解决这个问题,但是仔细一想这种做法不对。原因在于:用该公式可以算出节假日是星期几,但是当判断一年中有多少个星期六合星期日时还是得挨个儿算。
(2)应该用模拟的方法解决该问题。用变量sum表示一年中放假的天数;
   大致思路如下:
  if(当今天是星期六或星期日或节假日时){
     sum++;
   }

代码如下:
#include<iostream>
#include<algorithm>
using namespace std;

typedef struct date
{
    int m; ///节假日开始的月份 
    int d; ///节假日开始的日子 
    int len; ///节假日的长度 
}Date;

bool cmp(Date &d1,Date &d2) ///将节假日按照日期先后排序
{
    if(d1.m<d2.m){
        return true;
    }
    else if(d1.m==d2.m){
        if(d1.d<d2.d){
            return true;
        }
        else{
            return false;
        }
    }
    else{
        return false;
    }
}

bool isrun(int y)  ///判断是否为闰年
{
    if(y%4==0){
        if(y%100==0){
            if(y%400==0){
                return true;
            }
            else{
                return false;
            }
        }
        else{
            return true;
        }
    }
    else{
        return false;
    }
}


int main()
{
    Date a[10];
    a[0].m=1;a[0].d=1;a[0].len=1;
    a[1].m=5;a[1].d=1;a[1].len=1;
    a[2].m=10;a[2].d=1;a[2].len=3;
    a[3].m=12;a[3].d=25;a[3].len=1;
    a[4].len=3;a[5].len=1;a[6].len=1;a[7].len=1;
    
    a[8].m=0;a[8].d=0;a[8].len=0; ///作为边界条件防止程序的内存溢出 
    int mon[15]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    int y;
    cin>>y;
    for(int i=4;i<8;i++){
        cin>>a[i].m>>a[i].d;
    }
    sort(a,a+8,cmp); ///对节假日从小到大排序 
    
    int w;
    cin>>w;
    int days=365;
    if(isrun(y)){
        days=366;
        mon[2]=29;
    }
    int d=0;int m=1;
    int weekday=w-2;  ///初始化,目的是让0-6代表星期一到星期日 
    int sum=0;int p=0;
    for(int i=1;i<=days;i++){
        d++;
        weekday=(weekday+1)%7; ///0-6 代表 星期一到星期日 
        if(d>mon[m]){
            d=1;
            m++;
        }
        if(weekday==5 || weekday==6 || (m==a[p].m && d==a[p].d)){
            sum++;
            if(m==a[p].m && d==a[p].d){
                a[p].len--;   ///如果今天是节假日,那么将节假日的长度减1 
                if(a[p].len==0){
                    p++;      ///如果节假日长度变为0,说明此节假日已经结束,接下来应该考虑下一个节假日 
                }
                else{
                    a[p].d++;  ///如果节假日还未结束,那么就将节假日的开始日期向后移一天 
                    if(a[p].d>mon[a[p].m]){  ///注意:当向后移一天的时候,月份可能会随之改变 
                        a[p].d=1;
                        a[p].m++;
                    }
                }
            }
        }
    }
    cout<<sum<<endl;
    
}

总结:我的思路可能表达不清楚,但是解决这个问题的中心方法就是模拟,即从1月1日循环到12月31日,然后在做相关的操作。

如果还不能理解,大家可以先做一下下面这道题:

题干:

在X星系的广袤空间中漂浮着许多X星人造“炸弹”,用来作为宇宙中的路标。
每个炸弹都可以设定多少天之后爆炸。
比如:阿尔法炸弹2015年1月1日放置,定时为15天,则它在2015年1月16日爆炸。
有一个贝塔炸弹,2014年11月9日放置,定时为1000天,请你计算它爆炸的准确日期。

请填写该日期,格式为 yyyy-mm-dd 即4位年份2位月份2位日期。比如:2015-02-19

原文地址:https://www.cnblogs.com/ACPIE-liusiqi/p/8682905.html