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

POJ 3714 Raid

2017-08-10 20:10 323 查看
题意是平面上有一堆站点与士兵,要求士兵与站点最近的距离是多少。

本题为一道分治经典例题最近点对的问题的变形,需要添加条件是两点必须不属于同一集合即分属于站点与士兵。

求解最近点对问题的思路通常为分治。

不断地向下dfs,将原集合分为两份。现在点之间的距离便有了两种情况,第一种为同在一边可以进行递归处理。第二种为一个在左边,一个在右边。为了简化我们的时间复杂度,我们可以先算出这两边的最小值,将左右两边距离在这最小值之内的点存下来,进行暴力枚举计算距离,对于本题便可以AC。

下附AC代码。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#define maxn 200005
using namespace std;
int n;
int temp[maxn];
struct p
{
double x,y,flag;
}pos[maxn];
double myabs(double now)
{
return now>=0 ? now :-now;
}
bool operator <(p x,p y)
{
if(x.x!=y.x)
return x.x<y.x;
return x.y<y.y;
}
double dis(int l,int r)
{
return sqrt((pos[l].x-pos[r].x )*(pos[l].x-pos[r].x)+( pos[l].y-pos[r].y)*( pos[l].y-pos[r].y));
}
bool cmp(int i,int j)
{
return pos[i].y<pos[j].y;
}
double dfs(int l,int r)
{
double now=98765432187654321;
if(l==r)
return now;
if(l+1==r)
{
if(pos[l].flag==pos[r].flag)
return now;
else
return dis(l,r);
}

int mid=(l+r)/2;
double ans1=dfs(l,mid);
double ans2=dfs(mid+1,r);
now=min(ans1,ans2);

int cnt=0;
for(int i=l;i<=r;i++)
{
if(myabs(pos[i].x-pos[mid].x)<now)
{
temp[++cnt]=i;
}
}

sort(temp+1,temp+1+cnt,cmp);

for(int i=1;i<=cnt;i++)
for(int j=i+1;j<=cnt;j++)
{
if(myabs(pos[temp[i]].y-pos[temp[j]].y)>now)
break;
double d=dis(temp[i],temp[j]);
if(d<now && pos[temp[i]].flag!=pos[temp[j]].flag)
{
now=d;
}
}
return now;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
n*=2;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&pos[i].x,&pos[i].y);
if(i<=n/2)
pos[i].flag=1;
else
pos[i].flag=2;
}
sort(pos+1,pos+1+n);
printf("%.3lf\n",dfs(1,n));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: