1. 程式人生 > >bzoj2823[AHOI2012]信號塔

bzoj2823[AHOI2012]信號塔

設備 sub 距離 使用 pri clu 分開 line n+1

2823: [AHOI2012]信號塔

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1190 Solved: 545
[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

最小圓覆蓋裸題

 1 #include<bits/stdc++.h>
 2 #define N 500010
 3 using namespace std;
 4 int n;double r;
 5 const double eps=1e-8;
 6 struct P{
 7     double x,y;
 8     P operator - (const P &b)const{return (P){x-b.x,y-b.y};}
 9     double len(){return sqrt(x*x+y*y);}
10 }a[N],c;
11 
12 P getcentre(P A,P B,P C){
13 P ret; 14 double a1=B.x-A.x,b1=B.y-A.y,c1=(a1*a1+b1*b1)/2; 15 double a2=C.x-A.x,b2=C.y-A.y,c2=(a2*a2+b2*b2)/2; 16 double d=a1*b2-a2*b1; 17 ret.x=A.x+(c1*b2-c2*b1)/d; 18 ret.y=A.y+(a1*c2-a2*c1)/d; 19 return ret; 20 } 21 22 void getcircle(){ 23 random_shuffle(a+1,a+1+n); 24 c=a[1];r=0; 25 for(int i=1;i<=n;i++){ 26 if((a[i]-c).len()>r+eps){ 27 c=a[i];r=0; 28 for(int j=1;j<i;j++){ 29 if((a[j]-c).len()>r+eps){ 30 c.x=(a[i].x+a[j].x)/2; 31 c.y=(a[i].y+a[j].y)/2; 32 r=(a[j]-c).len(); 33 for(int k=1;k<j;k++){ 34 if((a[k]-c).len()>r+eps){ 35 c=getcentre(a[i],a[j],a[k]); 36 r=(a[i]-c).len(); 37 } 38 } 39 } 40 } 41 } 42 } 43 } 44 45 int main(){ 46 scanf("%d",&n); 47 for(int i=1;i<=n;i++) 48 scanf("%lf%lf",&a[i].x,&a[i].y); 49 getcircle(); 50 printf("%.2lf %.2lf %.2lf\n",c.x,c.y,r); 51 return 0; 52 }

bzoj2823[AHOI2012]信號塔