寻找最近点对

算法导论上一个经典算法,讲解可看 http://yzmduncan.iteye.com/blog/1432880 

 

AC代码的复杂度为 n*lgn*lgn,算法导论上讲还可以通过“预排序”,不用每次都按照y排序,复杂度可下降为n*lgn。

 

http://acm.hdu.edu.cn/status.php  上可以AC。

#include<stdio.h>
#include<math.h>
#include<algorithm>

using namespace std;

#define MAX 100005
#define Inf 2e20

struct Point {
    double x;
    double y;
};

Point a[MAX];
Point tmp[MAX];

int cmpX(Point a, Point b) {
    return a.x < b.x;
}
int cmpY(Point a, Point b) {
    return a.y < b.y;
}

double dis(Point* a, int i, int j) {
    return sqrt(
            (a[i].x - a[j].x) * (a[i].x - a[j].x)
                    + (a[i].y - a[j].y) * (a[i].y - a[j].y));
}

double minDis(int left, int right) {
    double d = Inf;
    if (left == right)
        return d;
    if (left + 1 == right) {
        return dis(a, left, right);
    }
    if (left + 2 == right) {
        return min(min(dis(a, left, left + 1), dis(a, left, right)),
                dis(a, left + 1, right));
    }

    int mid = left + (right - left) / 2;
    double minLeft = minDis(left, mid);
    double minRight = minDis(mid + 1, right);
    d = min(minLeft, minRight);

    int k = 0;
    for (int i = left; i <= right; i++) {
        if (fabs(a[mid].x - a[i].x) <= d) {
            tmp[k].x = a[i].x;
            tmp[k].y = a[i].y;
            k++;
        }
    }

    sort(tmp, tmp + k, cmpY);

    for (int i = 0; i < k; i++) {
        //j<i+8优化,否则会超时
        for (int j = i + 1; j < k && j < i + 8; j++) {
            if (dis(tmp, i, j) < d) {
                d = dis(tmp, i, j);
            }
        }

    }
    return d;

}

int main() {
    freopen("my.in", "r", stdin);
    int n;
    while (scanf("%d", &n) != EOF) {
        if (n == 0)
            break;
        for (int i = 0; i < n; i++) {
            scanf("%lf%lf", &a[i].x, &a[i].y);
        }
        sort(a, a + n, cmpX);
        double res = minDis(0, n - 1);

        printf("%.2lf\n", res / 2);
    }

    return 0;
}

 

posted @ 2014-09-04 17:43  jdflyfly  阅读(371)  评论(0编辑  收藏  举报