这个题题意是设计一个最大半径的铁环一次只能套住一个玩具,我的方法就是找到两个最近的玩具,用他们距离的一半当做铁环的半径。用了分治法中求最近点对。
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 1e5+10;
int n;
int a[maxn];
struct node
{
double x,y;
} c[maxn];
int cmpx(const node a,const node b)
{
return a.x<b.x;
}
int cmpy(int a,int b)
{
return c[a].y<c[b].y;
}
double dis(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double closest(int low,int high)\\求最近点对,分治法
{
if(low+1==high)
return dis(c[low],c[high]);
if(low+2==high)
return min(dis(c[low],c[low+1]),min(dis(c[low+1],c[high]),dis(c[low],c[high])));
int mid=(low+high)>>1;
double ans=min(closest(low,mid),closest(mid+1,high));
int cnt=0;
for(int i=low; i<=high; i++)
{
if(c[i].x>=c[mid].x-ans&&c[i].x<=c[mid].x+ans)
a[cnt++]=i;
}
sort(a,a+cnt,cmpy);
for(int i=0; i<cnt; i++)
{
int k=(i+7)>cnt?cnt:i+7;
for(int j=i+1; j<k; j++)
{
if(c[a[j]].y-c[a[i]].y>=ans)
break;
ans=min(ans,dis(c[a[i]],c[a[j]]));
}
}
return ans;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
for(int i=0; i<n; i++)
{
scanf("%lf %lf",&c[i].x,&c[i].y);
}
sort(c,c+n,cmpx);
printf("%.2lf\n",closest(0,n-1)/2.0);
}
return 0;
}