大意:给你一些加油站A的坐标,一些需要基地B的坐标,问你这两者之间的最小值。

 

思路:用一个标记来表示分别在A和B中,数组长度变大了两倍,然后就是最近点对模板题啦。

另外:输出是%.3f,我用%.3lf就WA。

 

CODE:

 

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define MAXN 100010
const int INF = 1e50;

struct node
{
    double x, y;
    int f;
}p[MAXN*2], ym[MAXN*2];

int n;

int cmpx(const node a, const node b)
{
    return a.x < b.x;
}

int cmpy(const node a, const node b)
{
    return a.y < b.y;
}

double dist(node a, node b)
{
    if(a.f * b.f > 0return INF;
    return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}

double getmind(node *p, int l, int r)
{
    if(l == r) return INF; //只有一个点
    if(l+1 == r) return dist(p[l], p[r]);    //只有两个点 
    int mid = (l+r)/2;
    double ans = min(getmind(p, l,mid), getmind(p, mid+1, r));  //注意是getmind(p, l, mid); 
    int yn = 0;
    for(int i = l; i <= r ; i++)   //divide
    {
        if(fabs(p[i].x - p[mid].x) <= ans)
        {
            ym[yn++] = p[i];
        }
    }
    sort(ym, ym+yn, cmpy); //预排序 
    for(int i = 0; i < yn; i++)
    {
        for(int j = i+1; j < yn; j++)
        {
            if(ym[j].y - ym[i].y >= ans) break;  //if(|y1-y2| >= ans) break;
            ans = min(ans, dist(ym[i], ym[j]));
        }
    }
    return ans;
}


int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
        {
            scanf("%lf%lf", &p[i].x, &p[i].y);
            p[i].f = 1;
        }
        for(int i = n; i < 2*n ; i++)
        {
            scanf("%lf%lf", &p[i].x, &p[i].y);
            p[i].f = -1;
        }
        sort(p, p+2*n, cmpx);
        double ans = getmind(p, 02*n-1);
            printf("%.3f\n", ans);
    }
    return 0;
}

 

posted on 2012-10-19 11:25  有间博客  阅读(762)  评论(0编辑  收藏  举报