[bzoj3210]花神的浇花集会

来源:互联网 发布:淘宝首页装修素材下载 编辑:程序博客网 时间:2024/04/29 15:02

题目大意

给你n个点,要你求一个点,横纵坐标是范围在0到100000之间的整数,使得该点到所有给定的点的切比雪夫距离最小。
n≤100000 0≤坐标范围≤100000

预备

首先两个点(x1,y1),(x2,y2)的切比雪夫距离为max(|x1x2|,|y1y2|)
然后把每个点的坐标变成(x+y,x-y),两个点切比雪夫距离变成了它们的曼哈顿距离。

满分算法

方法就很显然了。把每个坐标转成(x+y,x-y),然后由于求的是曼哈顿距离,可以把答案的横纵坐标分开来求,然后得到一个点(x,y)
然后把这个点坐标转回去就可以了吗?
不行!
答案求的是整点,然而这样求出来的坐标,奇偶性可能不一样,也就是转回去后可能是小数(如样例中求出的答案,转回去坐标是(1.5,1.5))。所以,对于奇偶性相同,直接转回去即可,如果不同,答案就在这个点上下左右四个整点中找。

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int maxn=100005;typedef long long LL;int n,x[maxn],y[maxn],xx[maxn],yy[maxn],ansx,ansy,X,Y;LL ans,s;double tx,ty;int main(){    scanf("%d",&n);    for (int i=0;i<n;i++)    {        scanf("%d%d",&x[i],&y[i]);        xx[i]=x[i]+y[i];        yy[i]=x[i]-y[i];    }    int j=0;    sort(xx,xx+n);    sort(yy,yy+n);    X=xx[n/2]; Y=yy[n/2];    if ((X+Y)%2==0)    {        ansx=(X+Y)/2;        ansy=(X-Y)/2;        ans=0;        for (int i=0;i<n;i++) ans+=max(abs(ansx-x[i]),abs(ansy-y[i]));        printf("%lld\n",ans);    }else    {        tx=(double)(X+Y)/2;        ty=(double)(X-Y)/2;        ans=1e17;        for (int a=0;a<2;a++)        {            int p=tx+a-0.5;            if (p>=0 && p<=1e5)            {                for (int b=0;b<2;b++)                {                    int q=ty+b-0.5;                    if (q>=0 && q<=1e5)                    {                        s=0;                        for (int i=0;i<n;i++) s+=max(abs(p-x[i]),abs(q-y[i]));                        if (s<ans) ans=s;                    }                }            }        }        printf("%lld\n",ans);    }    return 0;}
0 0
原创粉丝点击