杭电1007-----C语言实现

这道题花了好久的时间才做出来,刚开始没有思路,最后看了网上的解答,好难得样子,每次都没有看完,但是掌握了大概思想,今天试着做了一下,已ac

主要思想:先将点对按照x排序,再在x排好序的基础上按照y来排序,这个用qsort函数就可直接完成,然后主要就是分治法的运用,将点分成小份来寻找最近点对。每次有三种情况,即你分成的两堆点,最近点对的两点都在1.左边那堆  2.右边那堆  3.左边右边各一个,1, 2两种情况很好想,主要是第三种情况,关于第三种情况,网上有很多分析有详细说明最少只需要比较6个点即可,我的代码为了方便,我比较了7个点。

下面是我的代码:

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define ref 1e20;
#define min(a,b) a>b?b:a;

typedef struct point {
    double x, y;
}Point;

Point p[100000];

int cmpx_y(const void *a, const void *b) {
    double x1, y1, x2, y2;
    x1 = (*(Point *)a).x;
    y1 = (*(Point *)a).y;
    x2 = (*(Point *)b).x;
    y2 = (*(Point *)b).y;
    if (x1 != x2)
        return x1 > x2 ? -1 : 1;
    return y1 > y2 ? -1 : 1;
}

double length_(Point p1, Point p2) {
    return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}

double devide(int low, int high) {
    double min_ = ref;
    if (low == high)
        return ref;
    if (low + 1 == high) {
        return length_(p[low], p[high]);
    }
    int mid = (low + high) / 2;
    double d;
    int i, j;
    if (high - low < 7) {//总共都不足七个点时就直接算出来
        d = ref;
        for (i = low; i < high; i++) {
            for (j = i + 1; j < high; j++) {
                d = min(d, length_(p[i], p[j]));
            }
        }
        return d;

    }
    double d1 = devide(low, mid);
    double d2 = devide(mid + 1, high);
    min_ = min(d1, d2);
    for (i = mid - 3; i <= mid + 3; i++) {
        for (j = i + 1; j <= mid + 3; j++) {
            d = min(min_, length_(p[i], p[j]));
        }
    }
    return d;
}
int main() {
    int n;
    int i, j, k;
    while (scanf("%d", &n) != EOF&&n != 0) {

        for (i = 0; i < n; i++) {
            scanf("%lf%lf", &p[i].x, &p[i].y);
        }
        qsort(p, n, sizeof(p[0]), cmpx_y);
        double d = devide(0, n - 1);
        printf("%.2lf\n", d / 2);

    }
}

 

posted @ 2017-05-06 17:39  Carol淋  阅读(852)  评论(0编辑  收藏  举报