赞
踩
给定平面上 n n n 个点,找出其中的一对点的距离,使得在这 n n n 个点的所有点对中,该距离为所有点对中最小的
第一行: n n n ,保证 2 ≤ n ≤ 200000 2\le n\le 200000 2≤n≤200000 。
接下来 n n n 行:每行两个实数: x y x\ y x y ,表示一个点的行坐标和列坐标,中间用一个空格隔开。
仅一行,一个实数,表示最短距离,精确到小数点后面 4 4 4 位。
3
1 1
1 2
2 2
1.0000
数据保证 0 ≤ x , y ≤ 1 0 9 0\le x,y\le 10^9 0≤x,y≤109
P1429 平面最近点对(加强版)里最高赞题解写道:
我们充分发扬人类智慧:
将所有点全部绕原点旋转同一个角度,然后按 xx 坐标排序
根据数学直觉,在随机旋转后,答案中的两个点在数组中肯定不会离得太远
所以我们只取每个点向后的 5 个点来计算答案
这样速度快得飞起,在 n=1000000 时都可以在 1 s 内卡过
#include<bits/stdc++.h> #define pie acos(-1.0) #define int long long int using namespace std; const int N=4e5+124; int n; int ans=1e16; struct node{ int x,y; }a[N]; bool cmp(node x,node y){ return x.x<y.x; } int dist(int aa,int bb,int ac,int bc){ return (aa-ac)*(aa-ac)+(bb-bc)*(bb-bc); } void work(double ang){ ang=ang/180.0*pie; for(int i=1;i<=n;i++){ int ax=a[i].x,ay=a[i].y; int ex,ey; // ex=ax*cos(ang)-ay*sin(ang); // ey=ax*sin(ang)-ay*cos(ang); ex=(ax-0.0)*cos(ang)-(ay-0.0)*sin(ang)+0.0; ey=(ax-0.0)*sin(ang)+(ay-0.0)*cos(ang)+0.0; a[i].x=ex,a[i].y=ey; } sort(a+1,a+1+n,cmp); for(int i=1;i<=n;i++){ for(int j=i+1;j<=i+100&&j<=n;j++){ if(i==j)continue; // ans=min(ans,dist(a[i].x,a[i].y,a[j].x,a[j].y)); if(ans>dist(a[i].x,a[i].y,a[j].x,a[j].y)){ ans=dist(a[i].x,a[i].y,a[j].x,a[j].y); } } } } signed main(){ cin>>n; srand(time(NULL)); for(int i=1;i<=n;i++){ cin>>a[i].x>>a[i].y; } work(0); work(rand()%360); work(rand()%360); printf("%d\n",ans); return 0; }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。