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;
}

HDU 3124 Moonmist(最近园对模板)

时间: 2024-10-15 06:14:04

HDU 3124 Moonmist(最近园对模板)的相关文章

hdu 2255 二分图带权匹配 模板题

模板+注解在 http://blog.csdn.net/u011026968/article/details/38276945 hdu 2255 代码: //KM×î´ó×îСƥÅä #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; #define INF 0x0fffffff const int MAXN

hdu 1285 确定比赛名次 (模板题)

确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 11353    Accepted Submission(s): 4525 Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接

HDU 2222 Keyword Search AC自动机模板

#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <stack> #include <map> #include <ctime> #include <io

hdu 1530 Maximum Clique_最大团模板

题目链接 题意:给你一个有向图,求最大完全子图. 思路:套最大团模板 #include<stdio.h> #define MAXN 100 int n,map[MAXN][MAXN],best,num[MAXN]; bool dfs(int *tmp,int total,int cnt){ int i,j,k,a[MAXN]; if(!total){ if(best<cnt){ best=cnt; return true; } return false; } for(i=0;i<t

hdu 2987最大权闭合图模板类型题

/* 最大权闭合图模板类型的题,考验对知识概念的理解. 题意:现在要辞退一部分员工,辞退每一个员工可以的到一部分利益(可以是负的),并且辞退员工,必须辞退他的下属,求最大利益和辞退的最小人数. 最大权闭合图模板类型. 求出最大权后沿着源点s,dfs到的点就为最小的人数. 证明/* 转载:利用一个经典的trick:多关键字 > 建图前,对所有b[i],执行变换b[i]=b[i]*10000-1,然后,会惊异地发现, > 此时最大流所对应的方案就是满足辞退最少人数的了. > 为什么?显然,变

hdu 4828 Xor Sum (trie 树模板题,经典应用)

hdu 4825 题目链接 题意:给定n个数,然后给出m个询问,每组询问一个数x,问n中的数y使得x和y的异或和最大. 思路:字典树..把每个数转化成二进制,注意补全前导0,使得所有数都有相同的位数. 如果想要异或和最大,那么每一位尽可能都是1. 所以做法是,先构建字典树,然后每次find的时候,尽可能按照和当前寻找的数的位相反的位的方向走(如果有的话) 比如当前位是1,那我就往0的方向走. 需要注意的是,多组数据,每次要重新初始化一遍. 做法是 在struct 中重新 root = new N

HDU 1711 Number Sequence(KMP模板)

http://acm.hdu.edu.cn/showproblem.php?pid=1711 这道题就是一个KMP模板. 1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 5 const int maxn = 1000000+5; 6 7 int n,m; 8 9 int next[maxn]; 10 int a[maxn], b[maxn]; 11 12 void get_next() 13 { 1

hdu 4819 二维线段树模板

/* HDU 4819 Mosaic 题意:查询某个矩形内的最大最小值, 修改矩形内某点的值为该矩形(Mi+MA)/2; 二维线段树模板: 区间最值,单点更新. */ #include<bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 1010; int N, Q; struct Nodey { int l, r; int Max, Min; }; int locx[MAXN], l

HDU 3572 Task Schedule(ISAP模板&amp;amp;&amp;amp;最大流问题)

题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=3572 题意:m台机器.须要做n个任务. 第i个任务.你须要使用机器Pi天,且这个任务要在[Si  ,  Ei]区间内完毕才有效. 对于一个任务,仅仅能由一个机器来完毕.一个机器同一时间仅仅能做一个任务. 当然,一个任务能够分成几段不连续的时间来完毕.问,是否能做完所有任务. 题意非常清晰.也就是推断是否是满流. 对于网络流问题,模板大家都有,关键在于怎样建图(详见资料) 思路:今天问了龙哥,对建图