BZOJ 3170: [Tjoi 2013]松鼠聚会(切比雪夫距离)

来源:互联网 发布:淘宝卖家客服怎么搞 编辑:程序博客网 时间:2024/04/27 16:13

3170: [Tjoi 2013]松鼠聚会

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 837  Solved: 396
[Submit][Status][Discuss]

Description

有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。

Input

第一行给出数字N,表示有多少只小松鼠。0<=N<=10^5
下面N行,每行给出x,y表示其家的坐标。
-10^9<=x,y<=10^9

Output

表示为了聚会走的路程和最小为多少。

Sample Input

6
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2

Sample Output

20


解题思路:

切比雪夫距离,即各坐标差绝对值的最大值

首先我们如果想把曼哈顿距离转化成切比雪夫距离 那么就要把点(x,y)变成(x+y,x-y) 这样新点之间的切比雪夫距离就是原点之间的曼哈顿距离

同理,我们可以把切比雪夫距离转化成曼哈顿距离 即把点(x,y)变成((x+y)/2,(x-y)/2)

然后将横纵坐标排序 维护前缀和 分开讨论横纵坐标的曼哈顿距离即可

避免double,最后算出距离再除以2

#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <cmath>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#define LL long long using namespace std;const int MAXN = 100000 + 10;struct Point{    LL x, y;}p[MAXN];int n;LL X[MAXN], Y[MAXN];LL sum_x[MAXN], sum_y[MAXN];int main(){    while(scanf("%d", &n)!=EOF)    {        for(int i=1;i<=n;i++)            scanf("%lld%lld", &p[i].x, &p[i].y);        for(int i=1;i<=n;i++) X[i] = p[i].x + p[i].y, Y[i] = p[i].x - p[i].y;        sort(X + 1, X + 1 + n); sort(Y + 1, Y + 1 + n);        for(int i=1;i<=n;i++) sum_x[i] = sum_x[i-1] + X[i], sum_y[i] = sum_y[i-1] + Y[i];        LL ans = 1LL << 62;        for(int i=1;i<=n;i++)        {            int pos = lower_bound(X + 1, X + 1 + n, p[i].x + p[i].y) - X;            LL rx = pos * (p[i].x + p[i].y) - sum_x[pos] + (sum_x[n] - sum_x[pos]) - (n - pos) * (p[i].x + p[i].y);            pos = lower_bound(Y + 1, Y + 1 + n, p[i].x - p[i].y) - Y;            LL ry = pos * (p[i].x - p[i].y) - sum_y[pos] + (sum_y[n] - sum_y[pos]) - (n - pos) * (p[i].x - p[i].y);            ans = min(ans, rx + ry);        }        printf("%lld\n", ans / 2);            }    return 0;}


0 0
原创粉丝点击