题解:洛谷 AT_abc467_b Keep the Change
【题目来源】
洛谷:AT_abc467_b [ABC467B] Keep the Change
【题目描述】
Takahashi made purchases at \(N\) stores. Initially, he had \(10000\) yen.
At the \(i\)-th store, he bought an item worth \(A_i\) yen and paid \(B_i\) yen. Here, \(A_i \leq B_i\) holds. If \(S_i =\) keep, he did not receive the change, and if \(S_i =\) take, he received the change.
Find the amount of money he lost compared to the case where he received the change at every store. To be precise,
- let \(X\) yen be Takahashi's final amount of money, and
- let \(Y\) yen be Takahashi's final amount of money in the case where he received the change at every store.
Find \(Y - X\).
高橋在 \(N\) 家商店购物。最初,他有 \(10000\) 日元。
在第 \(i\) 家商店,他购买了一件价值 \(A_i\) 日元的商品,并支付了 \(B_i\) 日元。这里满足 \(A_i \leq B_i\)。如果 \(S_i =\) keep,他没有收到找零;如果 \(S_i =\) take,他收到了找零。
求与他在每家商店都收到找零的情况相比,他损失了多少钱。具体地,
- 设 \(X\) 日元为高橋最终持有的金额,
- 设 \(Y\) 日元为高橋在每家商店都收到找零的情况下最终持有的金额。
求 \(Y - X\)。
【输入】
The input is given from Standard Input in the following format:
\(N\)
\(A_1\) \(B_1\) \(S_1\)
\(A_2\) \(B_2\) \(S_2\)
\(\vdots\)
\(A_N\) \(B_N\) \(S_N\)
【输出】
Output the amount of money Takahashi lost compared to the case where he received the change at every store.
【输入样例】
3
1 2 keep
3 6 take
5 9 keep
【输出样例】
5
【核心思想】
-
问题分析:高橋在 \(N\) 家商店购物,初始有 \(10000\) 日元。每家商店购买 \(A_i\) 日元的商品,支付 \(B_i\) 日元。若 $S_i = $
keep则不要找零,若 $S_i = $take则收取找零 \(B_i - A_i\)。求与"每家都收找零"相比损失的金额,即 \(Y - X\)。这是一个模拟计算问题,核心在于分别计算实际最终金额 \(X\) 和理想最终金额 \(Y\)。 -
算法选择:
- 直接模拟:分别维护 \(X\)(实际)和 \(Y\)(理想),遍历每家商店更新金额
- 差值优化:\(Y - X\) 实际上只与 $S_i = $
keep的商店有关,因为 $S_i = $take时两者相同
-
关键步骤:
- 读入数据:读取 \(N\)
- 初始化:\(X \leftarrow 10000\),\(Y \leftarrow 10000\)
- 遍历每家商店(\(i\) 从 \(1\) 到 \(N\)):
- 读入 \(A_i, B_i, S_i\)
- \(Y \leftarrow Y - A_i\)(理想情况:实际花费为 \(A_i\))
- 若 $S_i = $
keep:\(X \leftarrow X - B_i\)(实际花费为 \(B_i\),损失找零 \(B_i - A_i\)) - 否则:\(X \leftarrow X - A_i\)(实际花费为 \(A_i\))
- 输出结果:\(Y - X\)
-
时间/空间复杂度:
- 时间复杂度:\(O(N)\),遍历商店一次
- 空间复杂度:\(O(1)\),仅维护两个金额变量
-
模拟与差值分析的核心思想:
- 理想与实际的对比:\(Y\) 表示"应该有多少钱",\(X\) 表示"实际有多少钱",差值 \(Y - X\) 即为损失金额
- 找零的实质:支付 \(B_i\) 购买 \(A_i\) 的商品,实际花费为 \(A_i\)(收找零)或 \(B_i\)(不收找零)。损失金额为 \(B_i - A_i\)
- 简化计算:\(Y - X = \sum_{S_i = \text{keep}} (B_i - A_i)\),即只累加未收找零商店的差额,可进一步优化为单次遍历直接累加
- 初始金额的抵消:\(X\) 和 \(Y\) 从相同初始值开始,最终差值只取决于过程中的差异,与初始值无关
- 适用于基础模拟、差额计算类入门问题
【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n; // n: 商店数量
int x; // x: 高橋实际最终持有的金额
int y; // y: 每家商店都收到找零时的最终金额
int main()
{
cin >> n; // 读入商店数量
x = y = 10000; // 初始金额均为 10000 日元
for (int i = 1; i <= n; i++) // 遍历每家商店
{
int a, b; // a: 商品价格; b: 支付金额
string s; // s: "keep" 或 "take"
cin >> a >> b >> s;
y -= b; // 理想情况:先支付 b 日元
y += (b - a); // 理想情况:收到找零 (b-a) 日元
if (s == "keep") // 实际情况:没有收到找零
{
x -= b; // 只支付了 b 日元,没有找零
}
else // 实际情况:收到了找零
{
x -= b; // 先支付 b 日元
x += (b - a); // 收到找零 (b-a) 日元
}
}
cout << y - x << endl; // 输出损失的金额(理想金额 - 实际金额)
return 0;
}
【运行结果】
3
1 2 keep
3 6 take
5 9 keep
5
浙公网安备 33010602011771号