您的位置:首页 > 大数据 > 人工智能

poj 3714 Raid 分治

2013-10-07 16:18 274 查看
先按横坐标排序,然后分治,合并的时候只需要处理两边x坐标差在d范围内的点即可。把这些点找出来之后,再按照y值排序,然后再检查y坐标差在d以内的点,那么可以保证每个点最多检查6个点(否则这些点之间必定存在距离小于d的点对),那么可以保证o(n)的合并。总的复杂度nlognlogn。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=1e5+9;
const double inf=1e11;
struct D
{
int x,y,id;
bool operator <(const D & xx) const
{
return x<xx.x;
}
}data[maxn<<1],now[maxn<<1];

struct cmp
{
bool operator()(D a,D b)
{
return a.y<b.y;
}
};

double cal(int t,int s)
{
if(now[t].id==now[s].id) return inf;
double a=now[t].x-now[s].x;
double b=now[t].y-now[s].y;
a*=a;
b*=b;
return sqrt(a+b);
}

double solve(int l,int r)
{
if(l==r) return inf;
int mid=l+r>>1;
double ret=solve(l,mid);
ret=min(ret,solve(mid+1,r));
int lon=0;
for(int i=mid;i>=l;i--)
{
if(data[mid+1].x-data[i].x>ret) break;
now[++lon]=data[i];
}
for(int j=mid+1;j<=r;j++)
{
if(data[j].x-data[mid].x>ret) break;
now[++lon]=data[j];
}
sort(now+1,now+1+lon);
for(int i=1;i<=lon;i++)
for(int j=i+1;j<=lon;j++)
{
if(now[j].y-now[i].y>ret) break;
ret=min(ret,cal(i,j));
}
return ret;
}

int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n+n;i++)
{
scanf("%d %d",&data[i].x,&data[i].y);
data[i].id=i>n;
}
sort(data+1,data+1+n+n);
double ans=solve(1,n+n);
printf("%.3f\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: