题目

题目来自蓝桥杯真题,因为我做这道题的时候的思路是:把2000年1月1日到2020年10月1日之间的所有日子都判断一次是否为月初或者周一,然后再按要求进行操作。但是我在遍历两个日期之间所有日子代码实现上耗费了较多的时间,故在此记录一下思路。
思路
可以看到题目中的日期包含了年月日。那么我们首先就要从开始的那个年份一直遍历到结束的那个年份(年遍历)。然后因为每一年都包含了12个月,所以我们要在年遍历中嵌套一个月份遍历,每年都要从1月遍历到12月。接着又因为每一个月都有n天,由于月份不同,月的天数也不同,所以我们还需要创建一个数组来储存不同月份的天数。
注意一个小细节,二月份的天数在闰年和平年是不一样的,所以我们要在年遍历中判断当前是闰年还是平年,然后针对不同情况对数组中二月份的天数进行动态修改。
实现
#include <stdio.h>int main(){// 千米数int k = 0 ;// 储存月份的数组,第二项为2月的月份,后面会在年遍历中进行动态修改!int months[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};// 储存开始年月日int year = 2000, month = 1, day = 1, week = 6;// 年遍历for (; year <= 2020; year++){// 判断是闰年还是平年,然后动态修改二月份的天数months[1] = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 ? 29 : 28;// 月遍历,一年指定有12个月,遍历完后在把月份重置为1(见第35行)for (; month <= 12; month++){// 日遍历,遍历条件为不同月份的天数,即months[month-1],到月尾了就重置(见31行)for (; day <= months[month - 1]; day++){// 判断当天是否为周一或月初,进而按题目要求加上不同的千米数k += (day == 1 || week == 1 ? 2 : 1);// 今天是星期几week = week == 7 ? 1 : week + 1;// 如果今天是2020年10月1日(终止日)即退出循环if (year == 2020 && month == 10 && day == 1)break;}// 月尾了,把日重置1day = 1;// 作用同第26行if (year == 2020 && month == 10 && day == 1)break;}// 年末了,把月重置为1月month = 1;}// 输出千米数printf("%d", k);return 0;}
运行结果:8879。
以上。
