喵哈囉~ 主人!今天我们来看一道超级可爱的题目,关于三个好朋友新年聚会的故事哦!让我们一起帮帮他们吧,喵~
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|
最小。
这是一个经典的数学问题,答案其实非常直观!最佳的见面地点,永远是所有坐标点中的中位数。
排序:首先,我们把三个朋友的位置
x1
,x2
,x3
从小到大排个序。比如说,排完序后我们得到三个点a
,b
,c
,其中a <= b <= c
。选择中位数:对于三个数来说,中位数就是中间那个数,也就是
b
。所以,最佳的见面地点就是b
点。计算距离:
- 住在
a
点的朋友需要走的路程是|a - b|
,因为b > a
,所以距离是b - a
。 - 住在
b
点的朋友一步都不用走,路程是0
(好幸福!)。 - 住在
c
点的朋友需要走的路程是|c - b|
,因为c > b
,所以距离是c - b
。
- 住在
求和:把这些距离加起来,总路程就是:
(b - a) + 0 + (c - b)
算一下……咦?+b
和-b
被抵消掉了耶!最后只剩下c - a
啦!
所以,最短的总距离,其实就是最大坐标减去最小坐标!是不是超级简单,喵~?
我们再用刚才的例子验证一下:7, 1, 4
。
- 最小坐标是
1
。 - 最大坐标是
7
。 - 最短总距离 =
7 - 1 = 6
。 和我们之前算出来的一样耶!太棒啦!
题解 (Solution Code)
下面就是实现这个想法的代码啦,非常简短哦!
#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
是偶数时:中位数是排序后中间两个数(比如第k
和k+1
个数)之间的任意一点(包括端点)。此时,无论选择这两个数之间的哪个点作为见面点,总距离都是一样的。
记住这个小技巧,下次再遇到类似“选择一个点使得总代价最小”的问题时,就可以先想想是不是和中位数有关哦!这样就能瞬间秒杀啦,嘿嘿~ 让你在朋友面前大显身手,purrr~