题目

image.png

题目来自蓝桥杯真题,因为我做这道题的时候的思路是:把2000年1月1日到2020年10月1日之间的所有日子都判断一次是否为月初或者周一,然后再按要求进行操作。但是我在遍历两个日期之间所有日子代码实现上耗费了较多的时间,故在此记录一下思路。

思路

可以看到题目中的日期包含了年月日。那么我们首先就要从开始的那个年份一直遍历到结束的那个年份(年遍历)。然后因为每一年都包含了12个月,所以我们要在年遍历中嵌套一个月份遍历,每年都要从1月遍历到12月。接着又因为每一个月都有n天,由于月份不同,月的天数也不同,所以我们还需要创建一个数组来储存不同月份的天数。

注意一个小细节,二月份的天数在闰年和平年是不一样的,所以我们要在年遍历中判断当前是闰年还是平年,然后针对不同情况对数组中二月份的天数进行动态修改。

实现

  1. #include <stdio.h>
  2. int main()
  3. {
  4. // 千米数
  5. int k = 0 ;
  6. // 储存月份的数组,第二项为2月的月份,后面会在年遍历中进行动态修改!
  7. int months[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  8. // 储存开始年月日
  9. int year = 2000, month = 1, day = 1, week = 6;
  10. // 年遍历
  11. for (; year <= 2020; year++)
  12. {
  13. // 判断是闰年还是平年,然后动态修改二月份的天数
  14. months[1] = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 ? 29 : 28;
  15. // 月遍历,一年指定有12个月,遍历完后在把月份重置为1(见第35行)
  16. for (; month <= 12; month++)
  17. {
  18. // 日遍历,遍历条件为不同月份的天数,即months[month-1],到月尾了就重置(见31行)
  19. for (; day <= months[month - 1]; day++)
  20. {
  21. // 判断当天是否为周一或月初,进而按题目要求加上不同的千米数
  22. k += (day == 1 || week == 1 ? 2 : 1);
  23. // 今天是星期几
  24. week = week == 7 ? 1 : week + 1;
  25. // 如果今天是2020年10月1日(终止日)即退出循环
  26. if (year == 2020 && month == 10 && day == 1)
  27. break;
  28. }
  29. // 月尾了,把日重置1
  30. day = 1;
  31. // 作用同第26行
  32. if (year == 2020 && month == 10 && day == 1)
  33. break;
  34. }
  35. // 年末了,把月重置为1月
  36. month = 1;
  37. }
  38. // 输出千米数
  39. printf("%d", k);
  40. return 0;
  41. }

运行结果:8879。

以上。