题解:洛谷 P1089 津津的储蓄计划

【题目来源】

洛谷:P1089 [NOIP 2004 提高组] 津津的储蓄计划 - 洛谷

【题目描述】

津津的零花钱一直都是自己管理。每个月的月初妈妈给津津 \(300\) 元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同。

为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在她那里,到了年末她会加上 \(20\%\) 还给津津。因此津津制定了一个储蓄计划:每个月的月初,在得到妈妈给的零花钱后,如果她预计到这个月的月末手中还会有多于 \(100\) 元或恰好 \(100\) 元,她就会把整百的钱存在妈妈那里,剩余的钱留在自己手中。

例如 \(11\) 月初津津手中还有 \(83\) 元,妈妈给了津津 \(300\) 元。津津预计 11 月的花销是 \(180\) 元,那么她就会在妈妈那里存 \(200\) 元,自己留下 \(183\) 元。到了 \(11\) 月月末,津津手中会剩下 \(3\) 元钱。

津津发现这个储蓄计划的主要风险是,存在妈妈那里的钱在年末之前不能取出。有可能在某个月的月初,津津手中的钱加上这个月妈妈给的钱,不够这个月的原定预算。如果出现这种情况,津津将不得不在这个月省吃俭用,压缩预算。

现在请你根据 \(2004\)\(1\) 月到 \(12\) 月每个月津津的预算,判断会不会出现这种情况。如果不会,计算到 \(2004\) 年年末,妈妈将津津平常存的钱加上 \(20\%\) 还给津津之后,津津手中会有多少钱。

【输入】

\(12\) 行数据,每行包含一个小于 \(350\) 的非负整数,分别表示 \(1\) 月到 \(12\) 月津津的预算。

【输出】

一个整数。如果储蓄计划实施过程中出现某个月钱不够用的情况,输出 \(-X\)\(X\) 表示出现这种情况的第一个月;否则输出到 \(2004\) 年年末津津手中会有多少钱。

注意,洛谷不需要进行文件输入输出,而是标准输入输出。

【输入样例】

290 230 280 200 300 170 340 50  90  80  200 60

【输出样例】

-7

【核心思想】

  1. 问题分析:津津每个月有固定收入(300元)和固定预算,她会在每月月末将手中整百的钱存入妈妈处(以100元为单位),剩余零钱留给自己。如果某个月初(即上月剩余 + 本月300元)不够预算,则计划失败。若全年成功,则年末时妈妈将本金加20%利息返还,加上津津手中最后的零钱,即为最终金额。本质是按月进行现金流模拟,涉及整数除法(取整百)和百分数计算。

  2. 算法选择

    • 逐月模拟:按照时间顺序,对每个月依次执行“收入 → 支出 → 储蓄”的流程。使用变量 ans 记录津津手中的零钱,mother 记录存入妈妈处的“百元”数量(即实际金额的1/100)。若某月出现 ans < 0,则输出 -i 并终止。若12个月全部通过,则最终金额 = ans + mother * 120(因为每存100元,年末返还120元)。
  3. 关键步骤

    • 初始化ans = 0(手中零钱),mother = 0(存钱数,单位为百元)。
    • 循环处理每个月
      1. 读入当月预算 yusuan
      2. 计算本月末手中零钱:ans = ans + 300 - yusuan
      3. ans < 0,说明本月钱不够用,输出 -i,结束程序。
      4. 将手中整百的部分存入妈妈处:mother += ans / 100(例如 ans=183,则 /100=1,存100元)。
      5. 手中保留零钱:ans = ans % 100
    • 输出结果:若循环正常结束,输出 ans + mother * 120(本金加20%利息)。
  4. 时间/空间复杂度

    • 时间复杂度:\(O(1)\),固定12次循环。
    • 空间复杂度:\(O(1)\),仅使用常数个变量。
  5. 模拟

    • 整百处理:存储时使用“百元”为单位(mother 存的是数量,不是金额),可以避免大数,且最终 mother * 100 就是本金,乘以 1.2mother * 120
    • 利息计算:妈妈最终返还的是本金 + 20%利息,即 存钱金额 * (1 + 20%) = 存钱金额 * 1.2。因为 mother 是百元数,所以返还金额为 mother * 100 * 1.2 = mother * 120
    • 失败判断:只要某个月出现 ans < 0,说明该月支出大于收入 + 上月剩余,计划失败,立即输出负的月份。
    • 适用场景:这类按月模拟的现金流问题(如工资管理、预算规划)非常适合用顺序模拟解决,核心是理清每一步的收支和储蓄操作。

【算法标签】

入门 #模拟

【代码详解】

#include <bits/stdc++.h>  // 包含标准库头文件(万能头文件)
using namespace std;      // 使用标准命名空间

/**
 * 主函数 - 程序入口
 * @return 程序执行状态码(0表示成功)
 */
int main()
{
    int ans = 0;         // 定义变量:当前剩余零钱
    int mother = 0;      // 定义变量:交给妈妈保管的整百金额(以100为单位计数)
    int yusuan;          // 定义变量:每月预算金额

    // 遍历12个月
    for (int i = 1; i <= 12; i++)
    {
        cin >> yusuan;   // 输入当月预算

        // 计算当月剩余金额(上月剩余+300津贴-当月预算)
        ans = ans + 300 - yusuan;

        // 检查是否出现赤字
        if (ans < 0)
        {
            printf("%d", -i);  // 输出出现赤字的月份(负数表示)
            return 0;          // 直接结束程序
        }

        // 将整百金额交给妈妈保管
        mother += ans / 100;   // 计算可以交给妈妈的整百金额数量
        ans = ans % 100;       // 保留剩余零钱
    }

    // 输出年末总金额(剩余零钱 + 妈妈保管金额*1.2)
    printf("%d", ans + mother * 120);

    return 0;            // 程序正常结束
}

【运行结果】

290
230
280
200
300
170
340
50
90
80
200
60
-7
posted @ 2026-08-30 09:18  团爸讲算法  阅读(12)  评论(0)    收藏  举报