hdu 1007 Quoit Design (最近点对)

题目大意:给出n件玩具坐标,制作一个圆环,使得其半径尽可能大,并且最多只能够圈中其中一件玩具。求此时的半径。

问题的本质就是求最近点对。方法是二分法。


#include <stdio.h>
#include <cmath>
#include <algorithm>
#define N 100005
using namespace std;
typedef double db;
struct P{
	db x,y;
}p[N],pt[N];
db dis(P a,P b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
bool cmp1(P a,P b) {return a.x<b.x;}
bool cmp2(P a,P b) {return a.y<b.y;}
db solve(int l,int r)
{
	if(r-l==1) return dis(p[r],p[l]);
	if(r-l==2) return min(dis(p[l],p[l+1]),min(dis(p[l+1],p[r]),dis(p[l],p[r])));
	int m=(l+r)>>1;
	db d=min(solve(l,m),solve(m+1,r));
	int i,j,cnt=0;
	for(i=l;i<=r;i++)
		if(p[i].x>=p[m].x-d&&p[i].x<=p[m].x+d)
			pt[cnt++]=p[i];
	sort(pt,pt+cnt,cmp2);
	for(i=0;i<cnt;i++)
		for(j=i+1;j<cnt;j++)
			if(pt[j].y-pt[i].y>=d) break;
			else d=min(d,dis(pt[i],pt[j]));
	return d;
}
int main()
{
	int i,n;
	while(scanf("%d",&n)!=EOF&&n)
	{
		for(i=0;i<n;++i) scanf("%lf%lf",&p[i].x,&p[i].y);
		sort(p,p+n,cmp1);
		printf("%.2lf\n",solve(0,n-1)/2);
	}
	return 0;
}

你可能感兴趣的:(hdu 1007 Quoit Design (最近点对))