POJ 3714 最近点对问题 分治法

题意:station和agent分别有n(1<=n<=100000)个点,求不同类别的最近点对距离。

题解:http://blog.csdn.net/w397090770/article/details/7295797 这里讲的很好。


#include <iostream>
#include <cstdio>
#include <memory.h>
#include <algorithm>
#include <cmath>
#define MAX(a , b) ((a) > (b) ? (a) : (b))
#define MIN(a , b) ((a) < (b) ? (a) : (b))
#define ABS(x) ((x) >= 0 ? (x) : (-(x)))
using namespace std;
const double inf = 1e50;
const int maxn = 100002;
struct P
{
    double x,y;
    int type;
}po[maxn << 1];
int middle[maxn << 1];
int n;

bool cmpx(P a,P b)
{
    return a.x < b.x;
}

bool cmpy(int a,int b)
{
    return po[a].y < po[b].y;
}

void read()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%lf %lf",&po[i].x,&po[i].y);
        po[i].type = 0;
    }
    for(int i=n;i<2*n;i++)
    {
        scanf("%lf %lf",&po[i].x,&po[i].y);
        po[i].type = 1;
    }
    n <<= 1;
    sort(po , po+n , cmpx);
    return;
}

double dis(int i,int j)
{
    if(po[i].type == po[j].type) return inf;
    return sqrt((po[i].x - po[j].x) * (po[i].x - po[j].x) + (po[i].y - po[j].y) * (po[i].y - po[j].y));
}

double Mindis(int l,int r)
{
    if(l >= r-1) return dis(l , r);
    int mid = (l + r) >> 1;
    double a = Mindis(l , mid);
    double b = Mindis(mid+1 , r);
    double d = MIN(a , b);
    int top = 0;
    for(int i=l;i<=r;i++)
    {
        if(ABS(po[i].x - po[mid].x) <= d)
        {
            middle[top++] = i;
        }
    }
    sort(middle , middle + top , cmpy);
    for(int i=0;i<top;i++)
    {
        int to = MIN(top-1 , i+6);
        for(int j=i+1;j<=to;j++)
        {
            d = MIN(d , dis(middle[i] , middle[j]));
        }
    }
    return d;
}

int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        read();
        printf("%.3f\n",Mindis(0,n-1));
    }
    return 0;
}

你可能感兴趣的:(POJ 3714 最近点对问题 分治法)