题解:学而思编程 最远距离
【题目来源】
学而思编程:最远距离
【题目描述】
小猴工作的城市非常繁华,并且城市中的道路都是相互平行或垂直的。如果在城市中道路上行走,不能用两个地点之间的直线距离计算长度。任意两个地点(设坐标分别为 \((x,y)\)与\((x',y')\))之间的距离为:
\(|x-x'|+|y-y'|\)
给定 \(n\) 个地点的坐标,请你帮助小猴计算这 \(n\) 个地点中哪两个地点的距离最远。
【输入】
第一行一个整数 \(n\);
接下来 \(n\) 行,每行两个整数 \(x_i,y_i\) 表示第 \(i\) 个地点的坐标,保证不会有两个地点的坐标相同。
【输出】
一行一个整数,表示最远距离。
【输入样例】
4
0 0
1 2
2 3
4 1
【输出样例】
5
【核心思想】
-
问题分析:给定 \(n\) 个点的坐标 \((x_i, y_i)\),求曼哈顿距离 \(|x_i - x_j| + |y_i - y_j|\) 的最大值。这是一个数学转化 + 极值扫描问题,关键在于利用曼哈顿距离的代数变形,将二维最值问题转化为一维极值差。
-
算法选择:
- 曼哈顿距离变形:利用绝对值的三角不等式性质,将 \(|x_i - x_j| + |y_i - y_j|\) 转化为两种形式的最大值
- 一维极值扫描:只需维护四个极值,\(O(n)\) 即可求得全局最远距离
-
关键步骤:
- 初始化:读取 \(n\)(点的数量),读取每个点的坐标 \((x_i, y_i)\)
- 数学变形:
- \(|x_i - x_j| + |y_i - y_j| = \max\begin{cases} (x_i + y_i) - (x_j + y_j) \\ (x_i - y_i) - (x_j - y_j) \\ -(x_i + y_i) + (x_j + y_j) \\ -(x_i - y_i) + (x_j - y_j) \end{cases}\)
- 等价于:\(\max\bigl( |(x_i + y_i) - (x_j + y_j)|, |(x_i - y_i) - (x_j - y_j)| \bigr)\)
- 维护四个极值(遍历所有点):
addmax = \max(addmax, x_i + y_i):\(x + y\) 的最大值addmin = \min(addmin, x_i + y_i):\(x + y\) 的最小值submax = \max(submax, x_i - y_i):\(x - y\) 的最大值submin = \min(submin, x_i - y_i):\(x - y\) 的最小值
- 计算答案:
ans = \max(addmax - addmin, submax - submin)
- 输出
ans
-
时间/空间复杂度:
- 时间复杂度:\(O(n)\),一次遍历求四个极值
- 空间复杂度:\(O(n)\),存储坐标数组(或 \(O(1)\) 在线处理)
-
曼哈顿距离变形的核心思想:
- 降维转化:曼哈顿距离 \(\max_{i,j} (|x_i - x_j| + |y_i - y_j|)\) 不直接等于 \(\max|x_i - x_j| + \max|y_i - y_j|\),但通过引入辅助变量 \(u = x + y\) 和 \(v = x - y\),可将其转化为 \(\max(\max|u_i - u_j|, \max|v_i - v_j|)\)
- 绝对值展开:\(|x_i - x_j| + |y_i - y_j|\) 的四种符号组合恰好对应 \((x_i + y_i) - (x_j + y_j)\)、\((x_i - y_i) - (x_j - y_j)\) 及其相反数,取绝对值后最大者即为答案
- 极值原理:一维数组中两元素差的最大值等于最大值减最小值,因此只需维护 \(u\) 和 \(v\) 的极值
- 避免枚举:将 \(O(n^2)\) 的暴力枚举优化为 \(O(n)\) 的极值扫描,效率提升显著
- 适用于"多维度曼哈顿距离最值"问题,通过坐标变换将高维绝对值和转化为低维独立极值问题
【解题思路】

【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n, x[1000005], y[1000005]; // 存储点的坐标
int addmax = -2e9, addmin = 2e9, submax = -2e9, submin = 2e9; // 最大值最小值初始化
int main()
{
cin >> n; // 输入点的数量
for (int i = 1; i <= n; i++) // 输入每个点的坐标
{
scanf("%d %d", &x[i], &y[i]);
}
// 遍历所有点,计算四个极值
for (int i = 1; i <= n; i++)
{
addmax = max(addmax, x[i] + y[i]); // 最大 x+y
addmin = min(addmin, x[i] + y[i]); // 最小 x+y
submax = max(submax, x[i] - y[i]); // 最大 x-y
submin = min(submin, x[i] - y[i]); // 最小 x-y
}
// 输出两种距离的最大值
cout << max((addmax - addmin), (submax - submin));
return 0;
}
【运行结果】
4
0 0
1 2
2 3
4 1
5
浙公网安备 33010602011771号