HDU--4312(坐标变换,切比雪夫距离)
2015-05-16 01:22:40
题目:跟 4311 题意差不多,给出N个点(1e5),找出一个点,使得这个点到其他所有点的切比雪夫距离和最小。(切比雪夫距离即:max(x 坐标差的绝对值,y 坐标差的绝对值 ))
思路:切比雪夫距离和棋盘很有关系,鉴于八皇后中的 x+y 表示法,我们
可以想到将每个点的坐标进行变换,(x,y) -> (x+y,x-y),这样一来,计算两点间的曼哈顿距离
就等于两点间切比雪夫距离的两倍。
|x1-x2| + |y1-y2| ---> |(x1+y1)-(x2+y2)| + |(x1-y1)-(x2-y2)| = max(|x1-x2| , |y1-y2|)
注意:可先将每个点的坐标 +2e9 以消除负数。
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB(a) push_back(a) typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; const int MAXN = 100010; const ll RA1 = 2e9; const ll RA2 = 4e9; ll sumx[MAXN],sumy[MAXN]; int n; struct point{ ll x,y; int id; }p[MAXN]; bool cmpx(point a,point b){ return a.x < b.x; } bool cmpy(point a,point b){ return a.y < b.y; } bool cmpid(point a,point b){ return a.id < b.id; } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i = 1; i <= n; ++i){ scanf("%lld%lld",&p[i].x,&p[i].y); p[i].x = p[i].x + p[i].y; p[i].y = p[i].x - p[i].y - p[i].y; p[i].x += RA1; p[i].y += RA1; p[i].id = i; } sort(p + 1,p + n + 1,cmpx); ll sum = 0; for(int i = 1; i <= n; ++i){ int id = p[i].id; sum += p[i].x; sumx[id] = p[i].x * (ll)i - sum; } sum = 0; for(int i = n; i >= 1; --i){ int id = p[i].id; sum += RA2 - p[i].x; sumx[id] += (RA2 - p[i].x) * (ll)(n + 1 - i) - sum; } sort(p + 1,p + n + 1,cmpy); sum = 0; for(int i = 1; i <= n; ++i){ int id = p[i].id; sum += p[i].y; sumy[id] = p[i].y * (ll)i - sum; } sum = 0; for(int i = n; i >= 1; --i){ int id = p[i].id; sum += RA2 - p[i].y; sumy[id] += (RA2 - p[i].y) * (ll)(n + 1 - i) - sum; } sort(p + 1,p + n + 1,cmpid); ll ans = sumx[1] + sumy[1]; for(int i = 2; i <= n; ++i) ans = min(ans,sumx[i] + sumy[i]); printf("%lld\n",ans >> 1); } return 0; }