【bzoj 1336&&1337&&2823】 最小圓覆蓋
阿新 • • 發佈:2018-12-15
Description
給出平面上N個點,N<=10^5.請求出一個半徑最小的圓覆蓋住所有的點。
這道題先對點隨機化處理,設前個點的最小圓覆蓋為,若當前要加入的點不在內則一定在的邊界上,然後在~中列舉,若不在圓內,就以為直徑構成圓,再在1~中列舉,用三點構成新圓即可,下面是程式(注意三題的輸出格式不同):
#include<stdio.h> #include<math.h> #include<algorithm> #include<stdlib.h> #include<iostream> using namespace std; const int N=100005; const double eps=1e-10; struct Point{ double x,y; Point operator +(const Point &p)const{ return (Point){x+p.x,y+p.y}; } Point operator /(const double p)const{ return (Point){x/p,y/p}; } }p[N],o,t1,t2; int n; double r; double L(Point &a,Point &b){ double x=a.x-b.x,y=a.y-b.y; return x*x+y*y; } void makec(Point &a,Point &b,Point &c){ double a1,a2,b1,b2,c1,c2; a1=2*(b.x-a.x); b1=2*(b.y-a.y); c1=(b.x+a.x)*(b.x-a.x)+(b.y+a.y)*(b.y-a.y); a2=2*(c.x-b.x); b2=2*(c.y-b.y); c2=(c.x+b.x)*(c.x-b.x)+(c.y+b.y)*(c.y-b.y); o.x=(c1*b2-c2*b1)/(a1*b2-a2*b1); o.y=(a1*c2-a2*c1)/(a1*b2-a2*b1); r=L(o,a); } inline bool in(Point &p){ return r-L(p,o)>=-eps; } int main(){ srand(9837528); int i,j,k; scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%lf%lf",&p[i].x,&p[i].y); } random_shuffle(p+1,p+n+1); makec(p[1],p[2],p[3]); for(i=4;i<=n;i++){ if(in(p[i])){ continue; } o=p[i],r=0; for(j=1;j<i;j++){ if(in(p[j])){ continue; } o=(p[i]+p[j])/2; r=L(p[i],o); for(k=1;k<j;k++){ if(in(p[k])){ continue; } makec(p[i],p[j],p[k]); } } } printf("%.10lf\n%.10lf %.10lf",sqrt(r),o.x,o.y); return 0; }