题目链接:传送门
思路:
1、随机选择三个点,成功的概论未1/8,所以用随机数多试几次就可以;
2、判断三点共线+求三点外心模板,判断这个圆求判断是否有大于(n+1)/2个点的距离为r。
(相信自己的代码,多试几次)
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const double eps = 1e-6;
struct Node
{
double x,y;
}cur[N];
struct Circle
{
Node pos;
double r;
};
int n,T;
//判断三个点是否共线
bool gongxian(Node a,Node b,Node c)
{
double Xba = (a.x - b.x),Yba = (a.y - b.y);
double Xca = (a.x - c.x),Yca = (a.y - c.y);
if(fabs(Xba*Yca - Xca*Yba) < eps) return true;
return false;
}
double dis(Node a,Node b)
{
return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
//三个点求外心
Node f(Node a,Node b,Node c)
{
double a1 = b.x - a.x,b1 = b.y - a.y,c1 = (a1*a1 + b1*b1)/2;
double a2 = c.x - a.x,b2 = c.y - a.y,c2 = (a2*a2 + b2*b2)/2;
double d = a1*b2-a2*b1;
return Node{a.x+(c1*b2-c2*b1)/d,a.y+(a1*c2-a2*c1)/d};
}
int main(void)
{
srand(29001);
cin>>T;
while(T--){
cin>>n;
for(int i=1;i<=n;i++) cin>>cur[i].x>>cur[i].y;
if(n == 1){
printf("%f %f %f\n",cur[1].x,cur[1].y,0.0);
continue;
}
else if(n <= 4){
printf("%f %f %f\n",(cur[1].x + cur[2].x)/2,(cur[1].y + cur[2].y)/2,
dis(cur[1],cur[2])/2);
continue;
}
Circle ans,tp;
while(true){
int t1 = rand()%n+1,t2 = rand()%n+1,t3 = rand()%n+1;
if(t1 == t2 || t2 == t3 || t1 == t3 || gongxian(cur[t1],cur[t2],cur[t3])) continue;
tp.pos = f(cur[t1],cur[t2],cur[t3]);
tp.r = dis(tp.pos,cur[t1]);
int cnt = 0;
for(int i=1;i<=n;i++){
if(fabs(dis(tp.pos,cur[i]) - tp.r) < eps) cnt++;
}
if(cnt >= (n+1)/2){
ans = tp;break;
}
}
printf("%f %f %f\n",ans.pos.x,ans.pos.y,ans.r);
}
return 0;
}