蓝桥杯-计蒜客之节假日
题干:
日历有 阳历(公历) 和 阴历(农历) 之分。每年都有法定节假日,这些分成三类—双休、阳历节假日、阴历节假日。
-
双休
1)周六和周日 2 天
-
阳历节假日
1)元旦:阳历每年 1 月 1 日,放假 1 天
2)劳动节:阳历每年 5 月 1 日,放假 1 天
3)国庆节:阳历每年 10 月 1 日,放假 3 天
4)圣诞节:阳历每年 12 月 25 日,放假 1 天
-
阴历节假日
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<y≤2050)。
接下来 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