Skip to content

喵哈囉~ 主人!今天我们来看一道超级可爱的题目,关于三个好朋友新年聚会的故事哦!让我们一起帮帮他们吧,喵~

Codeforces 723A - The New Year: Meeting Friends


题目大意 (Problem Description)

想象一下,有一条很长很长的直线 Ox,就像猫咪追着跑的毛线球一样,嘻嘻。有三位好朋友,他们分别住在 x1, x2, x3 这三个点上。

为了庆祝新年,他们想找一个地方见面。问题是,他们应该选在哪里见面,才能让他们三个走的总路程加起来最短呢?

举个例子喵: 如果三个朋友分别在 7, 1, 4。 他们可以选择在 4 这个点见面。

  • 第一个朋友从 7 走到 4,路程是 3
  • 第二个朋友从 1 走到 4,路程是 3
  • 第三个朋友本来就在 4,所以他不用动,路程是 0。 总路程就是 3 + 3 + 0 = 6。这会不会就是最短的呢?

题解方法 (Solution Approach)

这个问题呀,看起来好像要一个个点去试,但其实有个小秘密哦,喵!让本猫娘来告诉你吧!

我们的目标是找到一个见面点 p,使得总距离 |x1 - p| + |x2 - p| + |x3 - p| 最小。

这是一个经典的数学问题,答案其实非常直观!最佳的见面地点,永远是所有坐标点中的中位数

  1. 排序:首先,我们把三个朋友的位置 x1, x2, x3 从小到大排个序。比如说,排完序后我们得到三个点 a, b, c,其中 a <= b <= c

  2. 选择中位数:对于三个数来说,中位数就是中间那个数,也就是 b。所以,最佳的见面地点就是 b 点。

  3. 计算距离

    • 住在 a 点的朋友需要走的路程是 |a - b|,因为 b > a,所以距离是 b - a
    • 住在 b 点的朋友一步都不用走,路程是 0(好幸福!)。
    • 住在 c 点的朋友需要走的路程是 |c - b|,因为 c > b,所以距离是 c - b
  4. 求和:把这些距离加起来,总路程就是: (b - a) + 0 + (c - b) 算一下……咦?+b-b 被抵消掉了耶!最后只剩下 c - a 啦!

所以,最短的总距离,其实就是最大坐标减去最小坐标!是不是超级简单,喵~?

我们再用刚才的例子验证一下:7, 1, 4

  • 最小坐标是 1
  • 最大坐标是 7
  • 最短总距离 = 7 - 1 = 6。 和我们之前算出来的一样耶!太棒啦!

题解 (Solution Code)

下面就是实现这个想法的代码啦,非常简短哦!

cpp
#include <iostream>
#include <algorithm>
#include <vector>

// 这个问题要求我们找到一个点 p,
// 使得三个朋友到这个点的总距离 |x1 - p| + |x2 - p| + |x3 - p| 最小。
// 这是一个经典的“绝对值和最小化”问题。
// 它的最优解 p 就是所有坐标点 x1, x2, x3 的中位数。
//
// 对于三个点,我们先把它们排序,得到 a <= b <= c。
// 中位数就是 b。
//
// 当他们在 b 点相遇时:
// - 在 a 点的朋友走 b - a 的距离。
// - 在 b 点的朋友走 0 的距离。
// - 在 c 点的朋友走 c - b 的距离。
//
// 总距离 = (b - a) + 0 + (c - b) = c - a。
// 也就是说,最小总距离就是最大坐标减去最小坐标。

int main() {
    // 为了快一点点,加上这两句,养成好习惯喵~
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    int x1, x2, x3;
    // 读取三个朋友的位置,喵~
    std::cin >> x1 >> x2 >> x3;

    // 使用 std::min 和 std::max 找到三个数中的最小值和最大值
    // 用 {} 初始化列表超方便的!
    int min_coord = std::min({x1, x2, x3});
    int max_coord = std::max({x1, x2, x3});

    // 就像我们推导的一样,结果就是最大值减去最小值
    int total_distance = max_coord - min_coord;

    // 把答案打印出来吧!
    std::cout << total_distance << std::endl;

    return 0;
}

知识点介绍 (Knowledge Corner)

绝对值和与中位数 (Absolute Value Sum and Median)

这道题其实藏着一个非常有用的数学知识点,那就是**“绝对值和最小化”问题**,有时候也被叫做**“货仓选址问题”**。

它的核心结论是:

对于一条直线上的 n 个点,要找到一个点 p,使得所有点到 p 的距离之和 Σ|xi - p| 最小,这个最优的点 p 就是这 n 个点的中位数

  • n 是奇数时:中位数是唯一的,就是排序后最中间的那个数。就像我们这道题,n=3,中位数就是排序后的第 2 个点。
  • n 是偶数时:中位数是排序后中间两个数(比如第 kk+1 个数)之间的任意一点(包括端点)。此时,无论选择这两个数之间的哪个点作为见面点,总距离都是一样的。

记住这个小技巧,下次再遇到类似“选择一个点使得总代价最小”的问题时,就可以先想想是不是和中位数有关哦!这样就能瞬间秒杀啦,嘿嘿~ 让你在朋友面前大显身手,purrr~

Released under the MIT License.