Geometry Problem
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1722 Accepted Submission(s): 304
Special Judge
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.
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.
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.
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/2个点在圆上(数据保证有解)
解题思路:用普通的for循环肯定会超,因为数据保证有解,我们随机三个点,这三个点都在圆上的概率是0.5*0.5*0.5=0.125,三个点不都在圆上的概率是7/8,那么随机100次,概率就是(7/8)^100,约为1e-6,基本接近于0了,也就是说随机一百遍基本就能找到三个点都在圆上的情况,也就能找到那个圆的圆心和半径了。
注意坑点:1.n<5的情况要另考虑 2.三点共线 3.判断找到圆的条件(我一开始是cnt<=n/2,这样n如果从0开始遍历答案就不对了
附ac代码:
1 #include <iostream> 2 #include <string.h> 3 #include <algorithm> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cmath> 7 using namespace std; 8 typedef long long ll; 9 const int maxn = 1e5+10; 10 struct nod 11 { 12 double x; 13 double y; 14 }nu[maxn]; 15 int vis[maxn]; 16 double xx1,yy1,xx2,yy2,xx3,yy3; 17 void getr(double &x,double &y,double &r) 18 { 19 // printf("%lf %lf ",xx2,xx1); 20 double a=2*(xx2-xx1); 21 double b=2*(yy2-yy1); 22 double c=xx2*xx2-xx1*xx1+yy2*yy2-yy1*yy1; 23 double d=2*(xx3-xx2); 24 double e=2*(yy3-yy2); 25 double f=xx3*xx3-xx2*xx2+yy3*yy3-yy2*yy2; 26 x=(b*f-e*c)/(b*d-e*a); 27 y=(a*f-d*c)/(a*e-b*d); 28 r=sqrt((x-xx1)*(x-xx1)+(y-yy1)*(y-yy1)); 29 // printf("%lf %lf %lf ",x,y,r); 30 } 31 int main() 32 { 33 int t; 34 int n; 35 scanf("%d",&t); 36 while(t--) 37 { 38 39 scanf("%d",&n); 40 for(int i=0;i<n;++i) 41 scanf("%lf%lf",&nu[i].x,&nu[i].y); 42 if(n<=2) 43 { 44 printf("%lf %lf %lf ",nu[0].x,nu[0].y,0.0); 45 } 46 else if(n<=4) 47 { 48 double x,y,r; 49 x=(nu[0].x+nu[1].x)/2; 50 y=(nu[0].y+nu[1].y)/2; 51 r=sqrt((x-nu[0].x)*(x-nu[0].x)+(y-nu[0].y)*(y-nu[0].y)); 52 printf("%lf %lf %lf ",x,y,r); 53 } 54 else 55 { 56 while (true) 57 { 58 int coo1=rand()%n; 59 int coo2=rand()%n; 60 int coo3=rand()%n; 61 if(coo1==coo2 || coo1==coo3 || coo2==coo3) continue; 62 xx1=nu[coo1].x; yy1=nu[coo1].y; 63 xx2=nu[coo2].x; yy2=nu[coo2].y; 64 xx3=nu[coo3].x; yy3=nu[coo3].y; 65 if(fabs((yy3-yy2)*(xx2-xx1)-(xx3-xx2)*(yy2-yy1))<=1e-6) 66 continue; 67 double x=0,y=0,r=0; 68 getr(x,y,r); 69 int cnt=0; 70 for(int i=0;i<n;++i) 71 { 72 if(fabs(r*r- ((nu[i].x-x)*(nu[i].x-x)+(nu[i].y-y)*(nu[i].y-y)) )<=1e-6) 73 ++cnt; 74 } 75 if(cnt*2>=n) 76 { 77 printf("%lf %lf %lf ",x,y,r); 78 break; 79 } 80 } 81 } 82 } 83 return 0; 84 }