首页 > 代码库 > HDU 3124 Moonmist(最近园对模板)

HDU 3124 Moonmist(最近园对模板)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3124


寻找最近的两个圆的距离!


代码如下:

//计算几何模版。。。
//最近圆对
//HDU 3124

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
#define ll __int64
set <int>tree;
set <int>::iterator iter;
struct Point
{
	double x;
	int id, flag;
}p1[100017], p2[100017];
int tot1, tot2;
struct Q
{
	double x,y, r;
}q[50017];
int cmp(const void*p1, const void*p2)
{
	struct Point*a1=(struct Point*)p1;
	struct Point*a2=(struct Point*)p2;
	if (a1->x<a2->x) return -1;
	else if (a1->x==a2->x) return a2->flag-a1->flag;
	else return 1;
}
int cmp1(const void*p1, const void*p2)
{
	struct Q*a1=(struct Q*)p1;
	struct Q*a2=(struct Q*)p2;
	if (a1->y<a2->y)return -1;
	else if (a1->y==a2->y)return 0;
	else return 1;
}
double dis(double x1, double y1, double x2, double y2)
{
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
bool judge(int i, int j, double d)
{
	if (dis(q[i].x, q[i].y, q[j].x, q[j].y)<=q[i].r+q[j].r+2.0*d)
		return true;
	return false;
}
bool insert(int v,double d)
{
	iter = tree.insert(v).first;
	if (iter != tree.begin())
	{
		if (judge(v, *--iter,d))
		{
			return true;
		}
		++iter;
	}
	if (++iter != tree.end())
	{
		if (judge(v, *iter,d))
		{
			return true;
		}
	}
	return false;
}
bool remove(int v,double d)
{
	iter = tree.find(v);
	if (iter != tree.begin() && iter != --tree.end())
	{
		int a = *--iter;
		++iter;
		int b = *++iter;
		if (judge(a, b,d))
		{
			return true;
		}
	}
	tree.erase(v);
	return false;
}
bool check(double d)
{
	int i=1, j=1;
	while (i<=tot1&&j<=tot2)
	{
		if (p1[i].x-d<=p2[j].x+d)
		{
			if (insert(p1[i++].id, d))
				return true;
		}
		else
		{
			if (remove(p2[j++].id, d))
				return true;
		}
	}
	while (i<=tot1)
	{
		if (insert(p1[i++].id, d))
			return true;
	}
	while (j<=tot2)
	{
		if (remove(p2[j++].id, d))
			return true;
	}
	return false;
}
int main (void)
{
	int cases, n, i;
	scanf("%d",&cases);
	while (cases--)
	{
		scanf("%d",&n);
		tot1=tot2=0;
		for (i=1;i<=n;i++)
			scanf("%lf %lf %lf",&q[i].x,&q[i].y, &q[i].r);
		qsort(q+1,n,sizeof(struct Q),cmp1);
		for (i=1;i<=n;i++)
		{
			tot1++;
			p1[tot1].x=q[i].x-q[i].r;
			p1[tot1].id=i;
			p1[tot1].flag=1;
			tot2++;
			p2[tot2].x=q[i].x+q[i].r;
			p2[tot2].id=i;
			p2[tot2].flag=-1;
		}
		qsort(p1+1,tot1,sizeof(struct Point),cmp);
		qsort(p2+1,tot2,sizeof(struct Point),cmp);
		double head=0.0, tail=dis(q[1].x,q[1].y,q[2].x,q[2].y)+1.0, mid;
		while (tail-head>1e-8)
		{
			tree.clear();
			mid=(head+tail)/2.0;
			if (check(mid))
			{
				tail=mid;
			}
			else head=mid;}
		printf ("%.6lf\n",2.0*head);
	}
	return 0;
}