Problem Description
Alice is interesting in computation geometry problem recently. She found a interesting problem and solved it easily. Now she will give this problem to you :
You are given N distinct points (Xi,Yi) on the two-dimensional plane. Your task is to find a point P and a real number R, such that for at least ⌈N2⌉ given points, their distance to point P is equal to R.
Input
The first line is the number of test cases.
For each test case, the first line contains one positive number N(1≤N≤105).
The following N lines describe the points. Each line contains two real numbers Xi and Yi (0≤|Xi|,|Yi|≤103) indicating one give point. It’s guaranteed that N points are distinct.
Output
For each test case, output a single line with three real numbers XP,YP,R, where (XP,YP) is the coordinate of required point P. Three real numbers you output should satisfy 0≤|XP|,|YP|,R≤109.
It is guaranteed that there exists at least one solution satisfying all conditions. And if there are different solutions, print any one of them. The judge will regard two point’s distance as R if it is within an absolute error of 10−3 of R.
Sample Input
1
7
1 1
1 0
1 -1
0 1
-1 1
0 -1
-1 0
Sample Output
0 0 1
大致题意:给你n个点,让你找出一个圆,满足至少有一半的点(向上取整)满足这些点在圆上,保证有解,答案如果有多种任意输出一种即可。
思路:每次随机三个点,求出外接圆,然后判断是否满足条件。注意这三个点不能相同且不能再同一直线上。如果n小于4的话要特殊考虑下.还有就是答案不能大于1e9
代码如下
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
using namespace std;
const int maxn =1e5+5;
const double eps=1e-6;
struct Point
{
double x,y;
};
Point s[maxn];
int judge(int a,int b,int c)
{
if(a==b||a==c||b==c)
return 1;
if((s[b].x-s[a].x)*(s[c].y-s[a].y)==(s[c].x-s[a].x)*(s[b].y-s[a].y))
return 1;
return 0;
}
int main()
{
int T;
int n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&s[i].x,&s[i].y);
}
if(n==1)
{
printf("%lf %lf 1.00000\n",s[1].x+1,s[1].y);
continue;
}
else if(n<=4)
{
double r=sqrt((s[1].x-s[2].x)*(s[1].x-s[2].x)+(s[1].y-s[2].y)*(s[1].y-s[2].y))/2;
printf("%lf %lf %lf\n",(s[1].x+s[2].x)/2,(s[1].y+s[2].y)/2,r);
continue;
}
double x,y,r;
while(1)
{
int a = rand()%n+1;
int b = rand()%n+1;
int c = rand()%n+1;
if(judge(a, b, c))
continue;
//三点求圆心坐标公式
x = (s[a].x*s[a].x-s[b].y*s[b].y-s[b].x*s[b].x+s[a].y*s[a].y)*(s[a].y-s[c].y)-(s[a].x*s[a].x-s[c].y*s[c].y-s[c].x*s[c].x+s[a].y*s[a].y)*(s[a].y-s[b].y);
x /= 2*(s[a].y-s[c].y)*(s[a].x-s[b].x)-2*(s[a].y-s[b].y)*(s[a].x-s[c].x);
y = (s[a].x*s[a].x-s[b].y*s[b].y-s[b].x*s[b].x+s[a].y*s[a].y)*(s[a].x-s[c].x)-(s[a].x*s[a].x-s[c].y*s[c].y-s[c].x*s[c].x+s[a].y*s[a].y)*(s[a].x-s[b].x);
y /= 2*(s[a].y-s[b].y)*(s[a].x-s[c].x)-2*(s[a].y-s[c].y)*(s[a].x-s[b].x);
r = sqrt((s[a].x-x)*(s[a].x-x)+(s[a].y-y)*(s[a].y-y));
int sum = 0;
for(int i=1;i<=n;i++)
{
if(fabs(sqrt((s[i].x-x)*(s[i].x-x)+(s[i].y-y)*(s[i].y-y))-r)<1e-6)
sum++;
}
if(sum>=(n+1)/2&&fabs(x)<1e9&&fabs(y)<1e9&&fabs(r)<1e9)
break;
}
printf("%lf %lf %lf\n", x, y, r);
}
return 0;
}