题解:学而思编程 疫苗接种

【题目来源】

学而思编程:疫苗接种

【题目描述】

小猴前去接种疫苗,注射完第一剂后,医生告诉他过 \(21\) 天后再来注射第二剂。给定接种第一剂疫苗的日期(以年月日的顺序表示),请输出注射第二剂的日期(同样以年月日的顺序表示)。

【输入】

一行三个整数 \(y,m,d\),其中 \(y\) 表示年份、\(m\) 表示月份、\(d\) 表示天数。

【输出】

一行三个整数,表示接种第二剂疫苗的日期。

【输入样例】

2021 3 12

【输出样例】

2021 4 2

【核心思想】

  1. 问题分析:给定接种第一剂疫苗的日期(年 \(y\)、月 \(m\)、日 \(d\)),求 \(21\) 天后的日期。这是一个日期模拟 + 闰年处理问题,关键在于正确处理月份天数和跨年情况。

  2. 算法选择

    • 逐日推进:循环 \(21\) 次,每次将日期加 \(1\),处理跨月、跨年
    • 闰年判断\(2\) 月天数根据闰年调整(\(28\)\(29\) 天)
    • 月份天数表:预存每月天数,方便跨月判断
  3. 关键步骤

    • 初始化:读取 \(y, m, d\)
    • 闰年处理
      • \((y \bmod 4 = 0\)\(y \bmod 100 \neq 0)\)\(y \bmod 400 = 0\)
        • month[2]++:闰年 \(2\) 月有 \(29\)
    • 逐日推进(循环 \(i\)\(1\)\(21\)):
      • d++:天数加 \(1\)
      • d > month[m]d = 1, m++(跨月,进入下月第 \(1\) 天)
      • m > 12m = 1, y++(跨年,进入下一年 \(1\) 月)
    • 输出 \(y, m, d\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(21)\),固定循环次数
    • 空间复杂度:\(O(1)\),仅需月份天数表
  5. 日期模拟的核心思想

    • 逐日推进的鲁棒性:每天加 \(1\) 并检查边界,自然处理跨月、跨年,无需复杂公式
    • 闰年规则:四年一闰、百年不闰、四百年再闰,通过条件判断调整 \(2\) 月天数
    • 预存月份表month[1..12] 存储各月天数,避免大量 if-else,跨月判断简洁
    • 固定偏移量\(21\) 天偏移量不大,逐日模拟完全可行;若偏移量极大(如数年),可用日期差公式优化
    • 适用于"日期偏移计算"类问题,逐日模拟直观可靠,是处理复杂历法规则的基础方法

【算法标签】

模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int y, m, d;  // 年、月、日
int month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};  // 每月天数

int main()  // 主函数
{
    cin >> y >> m >> d;  // 输入起始年月日
    if (y%4==0 && y%100 !=0 || y%400==0)  // 判断是否为闰年
        month[2]++;  // 闰年2月有29天

    for (int i=1; i<=21; i++)  // 向后推移21天
    {
        d++;  // 天数加1
        if (d>month[m]) d=1, m++;  // 如果天数超过当月天数,进入下个月
        if (m>12) m = 1, y++;  // 如果月份超过12,进入下一年
    }
    cout << y << " " << m << " " << d << endl;  // 输出21天后的日期
    return 0;  // 程序正常结束
}

【运行结果】

2021 3 12
2021 4 2
posted @ 2026-07-05 14:41  团爸讲算法  阅读(7)  评论(0)    收藏  举报