题解:洛谷 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
【核心思想】
-
问题分析:津津每个月有固定收入(300元)和固定预算,她会在每月月末将手中整百的钱存入妈妈处(以100元为单位),剩余零钱留给自己。如果某个月初(即上月剩余 + 本月300元)不够预算,则计划失败。若全年成功,则年末时妈妈将本金加20%利息返还,加上津津手中最后的零钱,即为最终金额。本质是按月进行现金流模拟,涉及整数除法(取整百)和百分数计算。
-
算法选择:
- 逐月模拟:按照时间顺序,对每个月依次执行“收入 → 支出 → 储蓄”的流程。使用变量
ans记录津津手中的零钱,mother记录存入妈妈处的“百元”数量(即实际金额的1/100)。若某月出现ans < 0,则输出-i并终止。若12个月全部通过,则最终金额 =ans + mother * 120(因为每存100元,年末返还120元)。
- 逐月模拟:按照时间顺序,对每个月依次执行“收入 → 支出 → 储蓄”的流程。使用变量
-
关键步骤:
- 初始化:
ans = 0(手中零钱),mother = 0(存钱数,单位为百元)。 - 循环处理每个月:
- 读入当月预算
yusuan。 - 计算本月末手中零钱:
ans = ans + 300 - yusuan。 - 若
ans < 0,说明本月钱不够用,输出-i,结束程序。 - 将手中整百的部分存入妈妈处:
mother += ans / 100(例如 ans=183,则 /100=1,存100元)。 - 手中保留零钱:
ans = ans % 100。
- 读入当月预算
- 输出结果:若循环正常结束,输出
ans + mother * 120(本金加20%利息)。
- 初始化:
-
时间/空间复杂度:
- 时间复杂度:\(O(1)\),固定12次循环。
- 空间复杂度:\(O(1)\),仅使用常数个变量。
-
模拟:
- 整百处理:存储时使用“百元”为单位(
mother存的是数量,不是金额),可以避免大数,且最终mother * 100就是本金,乘以1.2即mother * 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
浙公网安备 33010602011771号