首页 > 代码库 > BZOJ 3170 TJOI 2013 松鼠聚会 切比雪夫距离

BZOJ 3170 TJOI 2013 松鼠聚会 切比雪夫距离

题目大意:给出平面上的一些点,求这些点中的一个使得所有点到这个点的切比雪夫距离之和最短。


思路:切比雪夫距离和曼哈顿距离是可以相互转化的,具体实现就是吧一个点的坐标由(x,y)变成(x - y,x + y),求切比雪夫距离就可以转化成求曼哈顿距离了,很好推。

然后就是暴力枚举每一个点,统计出来每个点的曼哈顿距离之和,最后取一个最小值。


CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
using namespace std;
 
pair<long long,int> X[MAX],Y[MAX];
 
struct Point{
    long long a,b,x,y;
     
    void Read(int p) {
        scanf("%lld%lld",&a,&b);
        x = a - b;
        y = a + b;
        X[p] = make_pair(x,p);
        Y[p] = make_pair(y,p);
    }
}point[MAX];
 
int points;
long long sum_x[MAX],sum_y[MAX];
long long ans[MAX];
 
int main()
{
    cin >> points;
    for(int i = 1; i <= points; ++i)
        point[i].Read(i);
    sort(X + 1,X + points + 1);
    sort(Y + 1,Y + points + 1);
    for(int i = 2; i <= points; ++i) {
        X[i].first -= X[1].first;
        Y[i].first -= Y[1].first;
    }
    X[1].first = Y[1].first = 0;
    for(int i = 1; i <= points; ++i) {
        sum_x[i] = sum_x[i - 1] + X[i].first;
        sum_y[i] = sum_y[i - 1] + Y[i].first;
    }
    for(int i = 1; i <= points; ++i) {
        ans[X[i].second] += X[i].first * (i - 1) - sum_x[i - 1];
        ans[X[i].second] += (sum_x[points] - sum_x[i]) - X[i].first * (points - i);
        ans[Y[i].second] += Y[i].first * (i - 1) - sum_y[i - 1];
        ans[Y[i].second] += (sum_y[points] - sum_y[i]) - Y[i].first * (points - i);
    }
    cout << *min_element(ans + 1,ans + points + 1) / 2 << endl;
    return 0;
}


BZOJ 3170 TJOI 2013 松鼠聚会 切比雪夫距离