题解:学而思编程 最远距离

【题目来源】

学而思编程:最远距离

【题目描述】

小猴工作的城市非常繁华,并且城市中的道路都是相互平行或垂直的。如果在城市中道路上行走,不能用两个地点之间的直线距离计算长度。任意两个地点(设坐标分别为 \((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

【核心思想】

  1. 问题分析:给定 \(n\) 个点的坐标 \((x_i, y_i)\),求曼哈顿距离 \(|x_i - x_j| + |y_i - y_j|\) 的最大值。这是一个数学转化 + 极值扫描问题,关键在于利用曼哈顿距离的代数变形,将二维最值问题转化为一维极值差。

  2. 算法选择

    • 曼哈顿距离变形:利用绝对值的三角不等式性质,将 \(|x_i - x_j| + |y_i - y_j|\) 转化为两种形式的最大值
    • 一维极值扫描:只需维护四个极值,\(O(n)\) 即可求得全局最远距离
  3. 关键步骤

    • 初始化:读取 \(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
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n)\),一次遍历求四个极值
    • 空间复杂度:\(O(n)\),存储坐标数组(或 \(O(1)\) 在线处理)
  5. 曼哈顿距离变形的核心思想

    • 降维转化:曼哈顿距离 \(\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
posted @ 2026-07-04 13:29  团爸讲算法  阅读(6)  评论(0)    收藏  举报