题解:洛谷 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

【核心思想】

  1. 问题分析:高橋在 \(N\) 家商店购物,初始有 \(10000\) 日元。每家商店购买 \(A_i\) 日元的商品,支付 \(B_i\) 日元。若 $S_i = $ keep 则不要找零,若 $S_i = $ take 则收取找零 \(B_i - A_i\)。求与"每家都收找零"相比损失的金额,即 \(Y - X\)。这是一个模拟计算问题,核心在于分别计算实际最终金额 \(X\) 和理想最终金额 \(Y\)

  2. 算法选择

    • 直接模拟:分别维护 \(X\)(实际)和 \(Y\)(理想),遍历每家商店更新金额
    • 差值优化\(Y - X\) 实际上只与 $S_i = $ keep 的商店有关,因为 $S_i = $ take 时两者相同
  3. 关键步骤

    • 读入数据:读取 \(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\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N)\),遍历商店一次
    • 空间复杂度:\(O(1)\),仅维护两个金额变量
  5. 模拟与差值分析的核心思想

    • 理想与实际的对比\(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
posted @ 2026-07-20 15:37  团爸讲算法  阅读(2)  评论(0)    收藏  举报