最小圆覆盖。。三个for是O(n)的QAQ。。因为随机化后新的点不在当前圆内的几率不大。。
学习了下求中垂线的姿势...
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<cstdlib> 5 #include<algorithm> 6 #define d double 7 using namespace std; 8 const int maxn=1e5+233; 9 const d eps=1e-8; 10 struct poi{d x,y;}a[maxn]; 11 struct cir{poi O;d r;}now; 12 poi operator +(poi a,poi b){return (poi){a.x+b.x,a.y+b.y};} 13 poi operator -(poi a,poi b){return (poi){a.x-b.x,a.y-b.y};} 14 poi operator /(poi a,d b){return (poi){a.x/b,a.y/b};} 15 int i,j,k,n,m; 16 17 inline d dis(poi a,poi b){ 18 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 19 } 20 inline poi rev(poi a){return (poi){a.y,-a.x};} 21 inline poi center(poi a,poi b,poi c){ 22 if(fabs((b.y-a.y)*(c.x-a.x)-(c.y-a.y)*(b.x-a.x))<eps){ 23 if(a.x>b.x)swap(a,b); 24 if(a.x>c.x)swap(a,c); 25 if(b.x>c.x)swap(b,c); 26 return (a+c)/2.0; 27 } 28 poi x1=(a+b)/2.0,x2=x1+rev(a-b),y1=(a+c)/2.0,y2=y1+rev(a-c); 29 if(fabs(y1.x-y2.x)<eps)swap(x1,y1),swap(x2,y2); 30 d k2=(y1.y-y2.y)/(y1.x-y2.x),b2=y2.y-y2.x*k2; 31 if(fabs(x1.x-x2.x)<eps)return (poi){x1.x,k2*x1.x+b2}; 32 d k1=(x1.y-x2.y)/(x1.x-x2.x),b1=x2.y-x2.x*k1; 33 d x=(b2-b1)/(k1-k2); 34 return (poi){x,k1*x+b1}; 35 } 36 inline bool oncir(poi a){ 37 return dis(a,now.O)<now.r+eps; 38 } 39 40 int main(){ 41 scanf("%d",&n);srand(n+233); 42 for(i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y); 43 random_shuffle(a+1,a+n+1); 44 now.O=(a[1]+a[2])/2.0,now.r=dis(now.O,a[1]); 45 for(i=3;i<=n;i++)if(!oncir(a[i])){ 46 now.O=(a[1]+a[i])/2.0,now.r=dis(a[i],a[1])/2.0; 47 for(j=2;j<i;j++)if(!oncir(a[j])){ 48 now.O=(a[i]+a[j])/2.0,now.r=dis(a[i],a[j])/2.0; 49 for(k=1;k<j;k++)if(!oncir(a[k])){ 50 now.O=center(a[i],a[j],a[k]); 51 now.r=dis(now.O,a[k]); 52 } 53 } 54 } 55 printf("%.6lf\n",now.r); 56 printf("%.6lf %.6lf\n",now.O.x,now.O.y); 57 return 0; 58 }
时间: 2024-10-07 06:38:29