现在的位置: 首页 > 综合 > 正文

poj 3714 变形的最近点对

2012年11月22日 ⁄ 综合 ⁄ 共 3536字 ⁄ 字号 评论关闭
Raid
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 7075   Accepted: 2098

Description

After successive failures in the battles against the Union, the Empire retreated to its last stronghold. Depending on its powerful defense system, the Empire repelled the six waves of Union's attack. After several sleepless nights of thinking, Arthur, General
of the Union, noticed that the only weakness of the defense system was its energy supply. The system was charged by N nuclear power stations and breaking down any of them would disable the system.

The general soon started a raid to the stations by N special agents who were paradroped into the stronghold. Unfortunately they failed to land at the expected positions due to the attack by the Empire Air Force. As an experienced general, Arthur
soon realized that he needed to rearrange the plan. The first thing he wants to know now is that which agent is the nearest to any power station. Could you, the chief officer, help the general to calculate the minimum distance between an agent and a station?

Input

The first line is a integer T representing the number of test cases.
Each test case begins with an integer N (1 ≤ N ≤ 100000).
The next N lines describe the positions of the stations. Each line consists of two integers X (0 ≤ X ≤ 1000000000) and Y (0 ≤ Y ≤ 1000000000) indicating the positions of the station.
The next following N lines describe the positions of the agents. Each line consists of two integers X (0 ≤ X ≤ 1000000000) and Y (0 ≤ Y ≤ 1000000000) indicating the positions of the agent.  

Output

For each test case output the minimum distance with precision of three decimal placed in a separate line.

Sample Input

2
4
0 0
0 1
1 0
1 1
2 2
2 3
3 2
3 3
4
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0

Sample Output

1.414
0.000
这是一道非常典型的最近点对,就是求上面一系列的点的最近距离,它有个特殊的要求是,这个距离的两个点必须是不同的两个集合里。这样的话,只需要将最近点对里求同一集合的两个点的距离设为无穷大。
下面是代码:
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<math.h>
const int N = 200002;
const double MAX = 10e100, eps = 0.00001; //mark!

struct Point {
    double x, y;
    int index;
    short set;//这个是核心必须保证两个点是在不同的点集中
}a[N], b[N], c[N];

inline double min(double p, double q) {
    return p < q ? p : q;
}

inline double dis(Point p, Point q) {
    double x1 = p.x - q.x;
    double y1 = p.y - q.y;
    return sqrt(x1*x1 + y1*y1);
}

int cmp_x(const void *p, const void *q) {
    double temp = ((Point *)p)->x - ((Point *)q)->x;
    if(temp>0) {
        return 1;
    } else if(fabs(temp) < eps) {
        return 0;
    } else {
        return -1;
    }
}

int cmp_y(const void *p, const void *q) {
    double temp = ((Point *)p)->y - ((Point *)q)->y;
    if(temp > 0) {
        return 1;
    } else if(fabs(temp)<eps){
        return 0;
    } else {
        return -1;
    }
}

void merge(Point p[], Point q[], int s, int m, int t) {
    int i, j, k;
    for(i=s,j=m+1,k=s; i<=m&&j<=t;) {
        if(q[i].y > q[j].y) {
            p[k++] = q[j];
            ++j;
        } else {
            p[k++] = q[i];
            ++i;
        }
    }

    while(i <= m) {
        p[k++] = q[i];
        ++i;
    }
    while(j <= t) {
        p[k++] = q[j];
        ++j;
    }
}

double closest(Point *a, Point *b, Point *c, int p, int q) {
    if(q-p == 1) {
        if(a[p].set != a[q].set)
            return dis(a[p], a[q]);
        else
            return MAX;
    }
    if(q-p == 2) {
        double x1, x2, x3;
        if(a[p].set != a[q].set)
            x1 = dis(a[p], a[q]);
        else
            x1 = MAX;
        if(a[p+1].set != a[q].set)
            x2 = dis(a[p+1], a[q]);
        else
            x2 = MAX;
        if(a[p].set != a[p+1].set)
            x3 = dis(a[p], a[p+1]);
        else
            x3 = MAX;
        double m = min(x1, x2);
        return min(m, x3);

    }

    int i, j, k, m = (p+q)>>1;
    double d1, d2;
    for(i=p,j=p,k=m+1; i<=q; ++i) {
        if(b[i].index <= m) {
            c[j++] = b[i];
        } else {
            c[k++] = b[i];
        }
    }

    d1 = closest(a, c, b, p, m);
    d2 = closest(a, c, b, m+1, q);
    double dm = min(d1, d2);
    merge(b, c, p, m, q);

    for(i=p,k=p; i<=q; ++i) {
        if(fabs(b[i].x - b[m].x) < dm) {
            c[k++] = b[i];
        }
    }

    for(i=p; i<k; ++i) {
        for(j=i+1; j<k&&c[j].y-c[i].y<dm; ++j) {
            if(c[j].set != c[i].set) {
                double temp = dis(c[j], c[i]);
                if(temp < dm) {
                    dm = temp;
                }
            }
        }
    }
    return dm;
}
//model end

int main() {
//freopen("in.txt", "r", stdin);
    int n, i, t;
    double ans;
    scanf("%d",&t);
    while(t--) {
        scanf("%d", &n);
        int mid = n;
        n = n<<1;
        for(i=0; i<n; ++i) {
            scanf("%lf%lf", &a[i].x, &a[i].y);
            if(i < mid)
                a[i].set = 0;
            else
                a[i].set = 1;
        }
        qsort(a, n, sizeof(a[0]), cmp_x);
        for(i=0; i<n; ++i) {
            a[i].index = i;
        }
        memcpy(b, a, sizeof(a[0])*n);
        qsort(b, n, sizeof(b[0]), cmp_y);
        ans = closest(a, b, c, 0, n-1);
        printf("%.3lf\n", ans);
    }
    return 0;
}


抱歉!评论已关闭.