津津的储蓄计划:C++实现与算法分析(洛谷P1089)
这道题目模拟了12个月的零花钱管理过程,需要跟踪每月资金流动,判断是否会出现资金不足,并计算年终总金额。核心思路是:初始化状态后,每月处理300元收入和预算支出,执行整百储蓄,年终计算1.2倍储蓄利息。关键点在于状态跟踪、储蓄逻辑实现和边界条件处理。解决方案使用两个变量分别记录当前金额和储蓄金额,通过循环处理每月收支,遇到资金不足立即返回负月份。注意处理整百储蓄和利息计算精度问题,避免浮点运算误差
·

题目思路解析
这道题目模拟了12个月的零花钱管理过程,考察状态模拟和边界条件处理能力。我们需要跟踪津津每个月的资金流动情况,判断是否会出现资金不足的情况,并计算年终总金额。
核心思考路径
- 初始化状态:津津初始手头金额为0,储蓄金额为0
- 月度循环处理:
- 每月月初获得300元
- 检查是否足够支付当月预算
- 执行储蓄计划(整百存储)
- 年终结算:计算储蓄利息和总金额
关键考核知识点
1. 状态跟踪与更新(⭐⭐⭐⭐⭐)
- 资金流动记录:需要维护两个变量
current_money:手中现金saved_money:储蓄金额
- 月度状态转移:
current_money += 300; // 月初收入 if (current_money < budget) { // 资金不足 return -current_month; } current_money -= budget; // 支付预算
2. 储蓄逻辑实现(⭐⭐⭐⭐)
- 整百存储规则:
if (current_money >= 100) { int save = (current_money / 100) * 100; saved_money += save; current_money -= save; }
3. 边界条件处理(⭐⭐⭐)
- 资金不足判断:检查
current_money + 300 < budget - 年终计算精度:利息计算
1.2 * saved_money - 月份索引处理:输出负月份时注意起始值
C++完整实现
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
int calculateSavings(const vector<int>& budgets) {
int current_money = 0;
int saved_money = 0;
for (int month = 0; month < 12; ++month) {
// 月初获得300元
current_money += 300;
// 检查是否足够支付预算
if (current_money < budgets[month]) {
return -(month + 1); // 返回负月份(1-based)
}
// 支付预算
current_money -= budgets[month];
// 储蓄整百金额
if (current_money >= 100) {
int save = (current_money / 100) * 100;
saved_money += save;
current_money -= save;
}
}
// 年终计算(利息20%)
return current_money + saved_money * 1.2;
}
int main() {
vector<int> budgets(12);
for (int i = 0; i < 12; ++i) {
cin >> budgets[i];
}
int result = calculateSavings(budgets);
if (result < 0) {
cout << result << endl;
} else {
cout << result << endl;
}
return 0;
}
代码解析与优化
1. 输入处理优化
// 使用vector预分配空间避免动态扩容
vector<int> budgets(12);
for (auto& budget : budgets) {
cin >> budget;
}
2. 利息计算优化
// 避免浮点数运算,使用整数计算
int total = current_money + saved_money + saved_money / 5;
3. 提前终止机制
// 发现资金不足立即返回
if (current_money < budgets[month]) {
return -(month + 1);
}
测试用例分析
| 测试案例 | 输入预算 | 预期输出 | 验证要点 |
|---|---|---|---|
| 案例1 | [290,230,...,60] | -7 | 资金不足情况 |
| 案例2 | [90,230,...,60] | 1890 | 完整年度计算 |
| 边界1 | [300]*12 | 360 | 每月刚好花完 |
| 边界2 | [0]*12 | 4320 | 全部储蓄情况 |
| 特殊1 | [350,0,...,0] | -1 | 首月不足 |
常见错误与修正
错误1:月份索引处理
// 错误:返回0-based索引
return -month; // 应该是month+1
修正:
return -(month + 1);
错误2:利息计算精度
// 错误:直接使用浮点乘法
double total = current_money + saved_money * 1.2;
修正:
int total = current_money + saved_money + saved_money / 5;
错误3:储蓄条件遗漏
// 错误:忽略恰好100元的情况
if (current_money > 100) // 应该是>=
修正:
if (current_money >= 100)
竞赛技巧总结
- 状态简化:只需跟踪两个变量,无需记录每月详情
- 提前终止:发现资金不足立即退出循环
- 整数运算:避免浮点数带来的精度问题
- 边界测试:特别注意首月和末月的情况
拓展思考
-
变形问题1:如果妈妈给的钱每月不同怎么办?
vector<int> incomes(12); // 修改状态更新逻辑 current_money += incomes[month]; -
变形问题2:允许中途取出储蓄(带惩罚)
// 增加储蓄取出逻辑 if (need_withdraw) { current_money += saved_money * 0.8; // 20%惩罚 saved_money = 0; } -
进阶挑战:多年度连续计算
// 增加年份循环 for (int year = 0; year < years; ++year) { // 年度计算逻辑 }
"编程竞赛中的模拟题,关键在于准确理解状态转移规则。通过这道题,我们掌握了资金流动模拟的核心技巧。"
关注并私信【储蓄】可获得:
- NOIP真题解析
- C++标准库文档
更多推荐



所有评论(0)