题目地址
解题思路
首先学习一下曼哈顿距离和切比雪夫距离即二者之间的转换。
那根据切比雪夫距离的定义,只要x, y这个点到它周围八个点的距离都是一的话,就是使用的切比雪夫距离。
对于给出的n个点,选择其中一个点并计算它到其他点的距离的话,由于切比雪夫距离定义为:d = max(|x1 - x2|,|y1 - y2|) 。计算所有点到当前点距离的时间复杂度为O(n)。那n个点就是O(n2)。时间上来说并不理想。
我们可以把给出的坐标转换为曼哈顿距离,曼哈顿距离的定义是 d = |x1 - x2| + |y1 - y2|。对于xi来说所有点到他的距离为 d = |x1 - xi| + |x2 - xi| + … + |xn - xi|
通过对所有点的x进行排序,就可以将公式里的绝对值去掉。
式子变为了 d = xi - x1 + xi - x2 +… + xi - xi + xi+1 - xi + … + xn - xi 也就是位置 i 之前的全变为xi减去当前点x值,i后面的全都不变。
再进行整理得到
进行一次遍历找到最小的距离即可,在转换的时候,可以先不除二,为了避免浮点数运算。在求出距离后再对距离除二即可。
参考博客:
https://blog.youkuaiyun.com/Code92007/article/details/103241897
https://www.cnblogs.com/adelalove/p/8612540.html
https://blog.youkuaiyun.com/qq_41997978/article/details/103213051?utm_source=app
AC代码
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
struct node
{
ll x, y;
};
struct node a[100010];
ll x[100010], y[100010];
ll sumx[100010],sumy[100010];
int main()
{
int n;
cin >> n;
for (int i=1; i<=n; i++)
{
cin >> x[i] >> y[i];
a[i].x = x[i] + y[i];
a[i].y = x[i] - y[i];
x[i] = a[i].x, y[i] = a[i].y;
}
sort (x+1, x+n+1);
sort (y+1, y+n+1);
for (int i=1; i<=n; i++)
{
sumx[i] = sumx[i-1] + x[i];
sumy[i] = sumy[i-1] + y[i];
}
ll minnum = 8e18;
for (int i=1; i<=n; i++)
{
int locationx = lower_bound(x+1, x+n+1, a[i].x) - x;
int locationy = lower_bound(y+1, y+n+1, a[i].y) - y;
ll temp = locationx * a[i].x - sumx[locationx] + (sumx[n] - sumx[locationx]) - (n-locationx)*a[i].x;
temp += locationy * a[i].y - sumy[locationy] + (sumy[n] - sumy[locationy]) - (n - locationy) * a[i].y;
minnum = min(minnum, temp);
}
cout << minnum / 2 << endl;
return 0;
}