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; }