题解:洛谷 AT_abc467_b Keep the Change

【题目来源】

洛谷:AT_abc467_b [ABC467B] Keep the Change

【题目描述】

高桥在 \(N\) 家商店进行了购物。一开始,他有 \(10000\) 日元。
在第 \(i\) 家商店,他购买了价格为 \(A_i\) 日元的商品,并支付了 \(B_i\) 日元。这里有 \(A_i \leq B_i\)。如果 \(S_i = \texttt{keep}\),表示他没有拿回找零;如果 \(S_i = \texttt{take}\),表示他拿回了找零。
请你计算,与在每一家商店都拿回找零的情况下相比,他损失了多少钱。具体来说,

  • \(X\) 为高桥实际剩下的钱数,
  • \(Y\) 为他在每家商店都拿回找零情况下的最终钱数。

请计算 \(Y - X\)

【输入】

输入从标准输入读入,格式如下:

\(N\)
\(A_1\) \(B_1\) \(S_1\)
\(A_2\) \(B_2\) \(S_2\)
\(\vdots\)
\(A_N\) \(B_N\) \(S_N\)

【输出】

输出高桥相较于每家商店都拿回找零的情况下损失的钱数。

【输入样例】

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  团爸讲算法  阅读(9)  评论(0)    收藏  举报