Skip to content

哈喽,各位同学好呀,我是你们的猫娘助教,喵~ 🐾

今天我们要看的是一道超级可爱的入门题目,关于一只时髦的小马 Valera 和他的马蹄铁!这道题非常适合刚开始学习编程和算法的同学哦,可以帮助我们熟悉一个很有用的小工具,喵。

让我们一起来看看吧!

题目大意

小马 Valera 要去参加一个派对,他想打扮得时髦一点。今年的流行风尚是四只马蹄铁颜色各不相同!Valera 翻出了去年剩下的四只马蹄铁,但他不确定这些马蹄铁的颜色是不是有重复的。

如果他有颜色相同的马蹄铁,他就需要去商店买新的,来凑齐四只不同颜色的马蹄铁。商店里有各种颜色的马蹄铁,Valera 的钱也足够。为了省钱,他想知道自己最少需要买几只新马蹄铁。

简单来说就是: 输入是 Valera 已有的四只马蹄铁的颜色(用四个数字表示)。我们要计算他至少需要买几只新的,才能拥有四只不同颜色的马蹄铁。

举个栗子,喵~

  • 如果他有颜色 1 7 3 3,这里面有重复的颜色 3。他实际上只有 173 这三种不同的颜色。为了凑齐四种,他还需要一种新颜色的马蹄铁,所以他需要买 1 只。
  • 如果他有颜色 7 7 7 7,他只有一种颜色 7。为了凑齐四种,他还需要三种新颜色的马蹄铁,所以他需要买 3 只。

是不是很简单呢?

题解方法

这个问题最关键的地方在于找出 Valera 已经拥有多少种不同颜色的马蹄铁,对吧,喵?

只要我们知道了不同颜色的数量,假设是 k 种,那么他需要买的马蹄铁数量就是 4 - k

那么,如何快速地统计不同颜色的数量呢?

想象一下,我们有一个神奇的魔法口袋,这个口袋有个特点:无论你放多少次同样的东西进去,它里面最终只会保留一个。比如说,你放了两个颜色为 3 的马蹄铁进去,口袋里只会有一个 3

这不就完美解决了我们的问题了嘛!我们把 Valera 的四只马蹄铁的颜色一个一个地扔进这个魔法口袋,最后数一数口袋里有几样东西,就知道不同颜色的数量啦!

在 C++ 中,这个“魔法口袋”就是 std::set(集合)容器。std::set 会自动帮我们处理重复的元素,只保留独一无二的值。

所以我们的解题步骤就是:

  1. 创建一个空的 std::set
  2. 读取输入的四个颜色数字。
  3. 把这四个数字依次插入到 std::set 中。
  4. 获取 std::set 的大小(也就是其中元素的数量),这个大小就是不同颜色的数量 k
  5. 计算 4 - k,这就是最终的答案啦,喵~

题解代码

下面就是用 C++ 实现这个思路的代码,猫娘我加上了一些注释,方便大家理解哦!

cpp
#include <iostream>
#include <set> // 要使用我们的魔法口袋 set,别忘了包含这个头文件哦!

/**
 * @brief 解决 "Is your horseshoe on the other hoof?" 问题
 *
 * 题目要求计算为了拥有四只不同颜色的马蹄铁,Valera 最少需要购买的数量。
 * 他已经有四只马蹄铁,但颜色可能重复。
 *
 * 核心思路是计算他已经拥有的不同颜色的数量。
 * 假设他有 'k' 种不同的颜色,那么他只需要保留这 'k' 种颜色各一只马蹄铁。
 * 为了凑齐四种不同的颜色,他需要再购买 4 - k 只他没有的颜色的马蹄铁。
 *
 * `std::set` 是一个非常理想的数据结构,因为它自动只存储唯一的元素。
 * 我们把四只马蹄铁的颜色都插入到一个 set 中,set 的最终大小就是不同颜色的数量。
 */
int main() {
    // 这两行是为了让输入输出快一点,在打比赛的时候是个好习惯,喵~
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    // 创建一个 set 来存放不同颜色的马蹄铁。
    // 颜色数值最大到 10^9,用 long long 更保险,虽然 int 也能装下。
    std::set<long long> distinct_colors;

    // 循环四次,读取 Valera 已有的四只马蹄铁的颜色
    for (int i = 0; i < 4; ++i) {
        long long color;
        std::cin >> color;
        // 喵~ 把颜色放进我们的魔法小集合里!
        // 如果颜色已经存在,insert 操作不会做任何事,set 的大小也不会变。
        distinct_colors.insert(color);
    }

    // set 的大小就是不同颜色的数量。
    // 需要购买的数量 = 目标数量(4) - 已有不同颜色的数量
    int horseshoes_to_buy = 4 - distinct_colors.size();

    // 输出最终答案
    std::cout << horseshoes_to_buy << std::endl;

    return 0;
}

喵喵小知识:C++ 中的 std::set

既然我们用到了 std::set,就来好好认识一下它吧!

std::set 是 C++ 标准模板库(STL)中的一种关联容器。你可以把它想象成一个数学上的“集合”。它有几个非常重要的特性:

  1. 唯一性 (Uniqueness) 这是 std::set 最核心的特点。它不允许存储重复的元素。每次你尝试用 insert() 方法添加一个新元素时,set 会先检查这个元素是否已经存在。如果存在,insert() 操作就会被忽略。这使得 set 成为统计不同元素数量的完美工具。

  2. 有序性 (Sorted)std::set 中存储的元素总是自动排序的。默认情况下,它会按照从小到大的顺序排列。虽然在这道题里我们没有用到这个特性,但在很多其他问题中,这个自动排序的功能会非常有用,喵!

常用操作:

  • set.insert(value): 向集合中插入一个元素。
  • set.size(): 返回集合中元素的数量。
  • set.count(value): 检查某个元素是否存在。如果存在,返回 1;否则返回 0
  • set.find(value): 查找一个元素,如果找到,返回指向该元素的迭代器;否则返回指向 set.end() 的迭代器。
  • set.erase(value): 从集合中删除一个元素。

总而言之,当你遇到需要处理不重复元素或者需要一个时刻保持有序的元素集合时,第一时间就应该想到 std::set 哦!它能让你的代码变得非常简洁和高效,喵~

希望这篇题解对你有帮助!如果还有其他问题,随时可以再来找我呀!拜拜,喵~ 💖

Released under the MIT License.