bzoj2823【AHOI2012】信号塔

2823: [AHOI2012]信号塔

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 819   Solved: 372
[ Submit][ Status][ Discuss]

Description

在野外训练中,为了确保每位参加集训的成员安全,实时的掌握和收集周边环境和队员信息非常重要,集训队采用
的方式是在训练所在地散布N个小型传感器来收集并传递信息,这些传感器只与设在集训地中的信号塔进行通信,
信号塔接收信号的覆盖范围是圆形,可以接收到所有分布在该集训区域内所有N个小型传感器(包括在该圆形的边
上)发出的信号。信号塔的功率与信号塔接收范围半径的大小成正比,因为是野外训练,只能使用事先储备好的蓄
电设备,因此在可以收集所有传感器信息的基础上,还应使得信号塔的功率最小。小龙帮助教官确定了一种信号塔
设置的方案,既可以收集到所有N个传感器的信号,又可以保证这个信号塔的功率是最小的。同学们,你们知道,
这个信号塔的信号收集半径有多大,它应该设置在何处吗?

Input

共N+1行,第一行为正整数N(1≤N≤1000000),表示队员个数。接下来N行,每行两个实数用空格分开,分别是第
i个队员的坐标X

Output

一行,共三个实数(中间用空格隔开),分别是信号塔的坐标,和信号塔 覆盖的半径。 (注:队员是否在边界上
的判断应符合他到圆心的距离与信号塔接收半径之差的绝对值小于10^-6

Sample Input

5
1.200 1.200
2.400 2.400
3.800 4.500
2.500 3.100
3.900 1.300

Sample Output

2.50 2.85 2.10

HINT

1≤N≤500000




随机增量法求最小圆覆盖




#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 1000005
#define eps 1e-6
using namespace std;
int n;
double r;
struct P
{
	double x,y;
	friend P operator +(P a,P b){return (P){a.x+b.x,a.y+b.y};}
	friend P operator -(P a,P b){return (P){a.x-b.x,a.y-b.y};}
	friend P operator /(P a,double b){return (P){a.x/b,a.y/b};}
}p[maxn],t;
inline double dis(P a,P b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline P rev(P a)
{
	return (P){a.y,-a.x};
}
inline P centre(P a,P b,P c)
{
	if (fabs((a.x-b.x)*(a.y-c.y)-(a.x-c.x)*(a.y-b.y))<=eps)
	{
		if (a.x<b.x) swap(a,b);
		if (a.x<c.x) swap(a,c);
		if (b.x<c.x) swap(b,c);
		return (a+c)/2;
	}
	P x1=(a+b)/2,x2=x1+rev(a-b),y1=(a+c)/2,y2=y1+rev(a-c);
	if (fabs(y1.x-y2.x)<eps) swap(x1,y1),swap(x2,y2);
	double k2=(y1.y-y2.y)/(y1.x-y2.x),b2=y2.y-y2.x*k2;
	if (fabs(x1.x-x2.x)<eps) return (P){x1.x,k2*x1.x+b2};
	double k1=(x1.y-x2.y)/(x1.x-x2.x),b1=x2.y-x2.x*k1;
	double x=(b2-b1)/(k1-k2);
	return (P){x,k1*x+b1};
}
int main()
{
	scanf("%d",&n);
	F(i,1,n) scanf("%lf%lf",&p[i].x,&p[i].y);
	random_shuffle(p+1,p+n+1);
	t=p[1];r=0.0;
	F(i,2,n) if (dis(t,p[i])>r+eps)
	{
		t=(p[1]+p[i])/2;r=dis(p[i],t);
		F(j,2,i-1) if (dis(t,p[j])>r+eps)
		{
			t=(p[i]+p[j])/2;r=dis(p[i],t);
			F(k,1,j-1) if (dis(t,p[k])>r+eps)
			{
				t=centre(p[i],p[j],p[k]);
				r=dis(p[i],t);
			}
		}
	}
	printf("%.2lf %.2lf %.2lf\n",t.x,t.y,r);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值