n^2的算法绝壁炸
自我感觉nlogn的算法——分治+简单优化
1、将点集按照先x较小优先,再y较小优先排序,求得区间(left, mid), (mid+1, right)中的最近点对的距离,则dis = 两者的较小值
2、枚举left到right的点对,如果fabs(p[mid].x-p[i].x) <= dis, 则将其加入tmpp[]点集,然后按照y较小优先排序tmpp
3、两个循环枚举tmpp点集,如果tmpp[j].y-tmpp[i].y >= dis,则可以退出第二个循环, 求出两点的最小距离更新dis
4、返回dis
*****************************************************************************************************************************************************************************************************
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 10;
const double INF = 1e20;
typedef struct
{
double x, y;
}point;
point p[maxn], tmpp[maxn];
bool cmpxy(point a, point b)
{
if(a.x != b.x) return a.x < b.x;
return a.y < b.y;
}
bool cmpy(point a, point b)
{
return a.y < b.y;
}
double getdis(point a, point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double close_pair(int l, int r);
int main()
{
int n;
while(scanf("%d", &n), n)
{
for(int i = 1; i <= n; ++i)
scanf("%lf %lf", &p[i].x, &p[i].y);
sort(p+1, p+n+1, cmpxy);
double ans = close_pair(1, n) * 0.5;
printf("%.2f\n", ans);
}
return 0;
}
double close_pair(int l, int r)
{
double dis = INF;
if(l == r) return dis;
if(l + 1 == r) return getdis(p[l], p[r]);
int mid = (l + r) >> 1;
double d1 = close_pair(l, mid);
double d2 = close_pair(mid+1, r);
dis = min(d1, d2);
int cnt = 0;
for(int i = l; i < r; ++i)
if(fabs(p[mid].x-p[i].x) <= dis)
tmpp[++cnt] = p[i];
sort(tmpp+1, tmpp+cnt+1, cmpy);
for(int i = 1; i <= cnt; ++i)
for(int j = i+1; j <= cnt; ++j)
{
if(tmpp[j].y-tmpp[i].y >= dis)
break;
dis = min(dis, getdis(tmpp[i], tmpp[j]));
}
return dis;
}