2 0 0 1 1 2 1 1 1 1 3 -1.5 0 0 0 0 1.5 0
0.71 0.00 0.75
Statistic | Submit | Discuss | Note
求平面上的最近点对,分治大法好
简单介绍思路,先把所有点按x坐标从小到大排好序,然后取中间点分成2份,分别求出左右两份里的最小值,最近点对可以在左边,在右边,或者横跨两部分,前面两者很好求,关键是第三者,设由前两者求出的最小值为x,那么我们可以找出横坐标距mid点在x之内的点,然后求出最小距离,进一步优化,我们可以把这些进行y坐标排序,如果对于当前i和j两个点,他们纵坐标距离已经大于等于x了,那么显然不是最近距离了(最好情况是x坐标相同,但这时也没有缩短最小距离)
#include<map> #include<set> #include<list> #include<stack> #include<queue> #include<vector> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef struct { double x, y; }point; point node[100100]; int pos[100100]; int cmpx(point a, point b) { return a.x < b.x; } int cmpy(int a, int b) { return node[a].y < node[b].y; } double dist(point a, point b) { return sqrt((double)(a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } double min(double a, double b) { return a < b ? a : b; } double min_distance(int low, int high) { //2个点 if(low == high - 1) return dist(node[low], node[high]); if(low == high - 2) return min(dist(node[low], node[low + 1]), min( dist(node[low], node[high]), dist(node[low + 1], node[high])) ); int mid = (low + high) >> 1; double cur_closed = min( min_distance(low, mid), min_distance(mid + 1, high) ); int cnt = 0; for(int i = low; i <= high; i++) { if(node[mid].x - cur_closed <= node[i].x && node[mid].x + cur_closed >= node[i].x) { pos[cnt++] = i; } } sort(pos, pos + cnt, cmpy); for(int i = 0; i < cnt; i++) { for(int j = i + 1; j < cnt; j++) { if(node[pos[j]].y - node[pos[i]].y >= cur_closed) { break; } cur_closed = min(cur_closed, dist(node[pos[j]], node[pos[i]])); } } return cur_closed; } int main() { int n; while(~scanf("%d", &n), n) { for(int i = 0; i < n; i++) { scanf("%lf%lf", &node[i].x, &node[i].y); } sort(node, node + n, cmpx); double ans = min_distance(0, n - 1); printf("%.2lf\n", ans / 2); } return 0; }