/* 隨機化初步 只看了一下午加一夜 可能理解的不到位 簡單說一下就是在一些狀況下咱們每次隨機的機率^隨機的次數≈1 關鍵是想清楚是否是≈1 而後看題 emmmmmm "我什麼都不會,我連搜題目都不會" 下午找了幾道隨機化的題目 第一道 POJ 3318 暴力也能水過去 並且隨機化比較好像 並且poj GG了 第二道 暴力題就是 而後博主以爲隨機化好玩就寫了一發 終於找到一個比較適合隨機化入門的題目 Hdu 6242 題意 找一個點一個半徑肯定一個圓,使得給出的n個點有一半以上在這個圓上 每次隨機的找3個點肯定一個圓 看看這個圓合不合法 每次這三個都在答案圓上的機率是1/8 而後咱們隨機1000次 幾乎必定能隨機到答案圓 而後有一些坑 1.n<=4要特判 由於可能找不到3點不共線 2.精度爲題,雖然要求3位小數,而後只要是個double就不能用== 3.*******特判的時候輸出記得加回車(相似的打Case:**) 4.題目條件讀全 半徑和點左邊小於1e9 */ #include<cstdio> #include<cstring> #include<iostream> #include<cstdlib> #include<cmath> #define maxn 100010 using namespace std; int T,n; double R; struct node{ double x,y; }A[maxn]; node Get_p(node p1,node p2,node p3){ double a,b,c,d,e,f;node p; a=2*(p2.x-p1.x); b=2*(p2.y-p1.y); c=p2.x*p2.x+p2.y*p2.y-p1.x*p1.x-p1.y*p1.y; d=2*(p3.x-p2.x); e=2*(p3.y-p2.y); f=p3.x*p3.x+p3.y*p3.y-p2.x*p2.x-p2.y*p2.y; p.x=(b*f-e*c)/(b*d-e*a); p.y=(d*c-a*f)/(b*d-e*a); R=(p.x-p1.x)*(p.x-p1.x)+(p.y-p1.y)*(p.y-p1.y); return p; } bool Ok(node p1,node p2,node p3){ return (p1.y-p2.y)*(p2.x-p3.x)==(p2.y-p3.y)*(p1.x-p2.x); } double Cal(node i,node j){ return (i.x-j.x)*(i.x-j.x)+(i.y-j.y)*(i.y-j.y); } double Abs(double x){ return x>0?x:-x; } int main(){ scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lf%lf",&A[i].x,&A[i].y); if(n==1){ printf("%lf %lf %lf\n",A[1].x-1,A[1].y,1.0);continue; } if(n<=4){ printf("%lf %lf %lf\n",(A[1].x+A[2].x)/2,(A[1].y+A[2].y)/2,sqrt(Cal(A[1],A[2]))/2);continue; } for(int k=1;k<=1000;k++){ int x=rand()%n+1; int y=rand()%n+1; while(y==x)y=rand()%n+1; int z=rand()%n+1; while(z==y||z==x||Ok(A[x],A[y],A[z])) z=rand()%n+1; node p=Get_p(A[x],A[y],A[z]); if(Abs(p.x)>1e9||Abs(p.y)>1e9||Abs(sqrt(R))>1e9)continue; int sum=0;for(int i=1;i<=n;i++) if(Abs(Cal(A[i],p)-R)<1e-6)sum++; if(sum>=(n+1)/2){ printf("%lf %lf %lf\n",p.x,p.y,sqrt(R));break; } } } return 0; }