2013-03-15 21:34:12Morris

[ZJ][D&C] a638. Closest-pair problem


內容 :

在二維座標平面上有 N 個點,

請找出最近兩點的距離。

距離公式如下:

輸入說明 :

每個測資點只有一組測資

第一行只有一個整數 N (1 < N ≤ 3,000,000) 代表有幾個點

接下來 N 行每行有兩個整數 x, y (0 ≤ x, y ≤ 10,000,000) 代表每個點的座標

座標已排序且不會有重複的點 

輸出說明 :

請輸出最近點對的距離

答案請四捨五入到小數點後第四位 

範例輸入 :

3
1 7
7 10
10 9

範例輸出 :

3.1623

提示 :

出處 :

(管理:example)

DJWS 演算法筆記中 所描述的 D&C 中,有些許的不一樣,
在 merge 的時候,這裡的代碼十分偷懶。


/*****************************************************************/
/*  Problem: a638 "Closest-pair problem" from                    */
/*  Language: CPP (1951 Bytes)                                   */
/*  Result: AC(108ms, 10.4MB) judge by this@ZeroJudge            */
/*  Author: morris1028 at 2013-03-11 12:58:31                    */
/*****************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define oo 100000000
typedef struct {
    float x, y;
}Point;
Point D[3000000];
int cmp(const void *i, const void *j) {
    Point *x, *y;
    x = (Point *)i, y = (Point *)j;
    if(x->x != y->x)
        return x->x - y->x < 0 ? 1 : -1;
    return x->y - y->y < 0 ? 1 : -1;
}
double Min(double x, double y) {
    return x < y ? x : y;
}
double Merge(int l, int m, int r, double d) {
    double midL = D[m].x;
    int i, j;
    for(i = m; i >= l; i--) {
        if((D[i].x-midL)*(D[i].x-midL) >= d)    break;
        for(j = m+1; j <= r; j++) {
            if((D[i].x-D[j].x)*(D[i].x-D[j].x) >= d)    break;
            d = Min(d, (D[i].x-D[j].x)*(D[i].x-D[j].x)+(D[i].y-D[j].y)*(D[i].y-D[j].y));
        }
    }
    return d;
}
double ClosestPair(int l, int r, double *dis) {
    if(l < r) {
        if(l == r-1) {
            return (D[l].x-D[r].x)*(D[l].x-D[r].x) + (D[l].y-D[r].y)*(D[l].y-D[r].y);
        }
        int m = (l+r)>>1;
        *dis = Min(*dis, ClosestPair(l, m, dis));
        *dis = Min(*dis, ClosestPair(m+1, r, dis));
        *dis = Min(*dis, Merge(l, m, r, *dis));
        return *dis;
    }
    return oo;
}
inline int readchar() {
    const int N = 1048576;
    static char buf[N];
    static char *p = buf, *end = buf;
    if(p == end) {
        if((end = buf + fread(buf, 1, N, stdin)) == buf) return EOF;
        p = buf;
    }
    return *p++;
}
inline int ReadInt(int *x) {
    static char c, neg;
    while((c = readchar()) < '-')    {if(c == EOF) return 0;}
    neg = (c == '-') ? -1 : 1;
    *x = (neg == 1) ? c-'0' : 0;
    while((c = readchar()) >= '0')
        *x = (*x << 3) + (*x << 1) + c-'0';
    *x *= neg;
    return 1;
}
int main() {
    int N, i, x, y;
    ReadInt(&N);
    for(i = 0; i < N; i++) {
        ReadInt(&x), ReadInt(&y);
        D[i].x = x, D[i].y = y;
    }
    double distance = oo;
    distance = ClosestPair(0, N-1, &distance);
    distance = sqrt(distance);
    printf("%.4lf\n", distance);
    return 0;
}