/* 随机化初步 只看了一下午加一晚上 可能理解的不到位 简单说一下就是在一些情况下我们每次随机的概率^随机的次数≈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 ",A[1].x-1,A[1].y,1.0);continue; } if(n<=4){ printf("%lf %lf %lf ",(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 ",p.x,p.y,sqrt(R));break; } } } return 0; }