题目
题目来自蓝桥杯真题,因为我做这道题的时候的思路是:把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;
}
// 月尾了,把日重置1
day = 1;
// 作用同第26行
if (year == 2020 && month == 10 && day == 1)
break;
}
// 年末了,把月重置为1月
month = 1;
}
// 输出千米数
printf("%d", k);
return 0;
}
运行结果:8879。
以上。