HDU 6242 Geometry Problem (隨機數+計算幾何)
Geometry Problem
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 4362 Accepted Submission(s): 772Special JudgeProblem 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 Npoints 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
Source
題意:給出N個點,讓你確定一個圓,使得至少有ceil(N/2)個點在圓上,輸出這個圓的半徑和圓心座標
思路:題目已經說明肯定會有一個符合條件的圓存在,最多100000個點,至少有50000個點在一個圓上,因為不再同一條直線上的三點確定一條直線,我們任意取三個點,這三個點能確定符合題意的圓的概率為C(3,50000)/C(3,100000),大約1/8,所以隨機去個幾十次肯定能取到符合題意的三個點,隨機取點的過程就用到了隨機數了
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
const double eps = 1e-8;
const double inf = 1e20;
int sgn(double x)
{
if(fabs(x) < eps) return 0;
if(x < 0) return -1;
else return 1;
}
struct Point
{
double x,y;
Point(){}
Point(double _x,double _y)
{
x = _x;
y = _y;
}
void input()
{
scanf("%lf %lf",&x,&y);
}
double operator *(const Point &b) const
{
return x * b.x + y * b.y;
}
Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
}
Point operator + (const Point &b) const
{
return Point(x + b.x,y + b.y);
}
Point operator / (const double &k) const
{
return Point(x / k,y / k);
}
double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
}
Point rotleft()
{
return Point(-y,x);
}
double distance(Point p)
{
return hypot(x - p.x,y - p.y);
}
}p[MAXN];
struct Line
{
Point s,e;
Line(){}
Line(Point _s,Point _e)
{
s = _s;
e = _e;
}
bool parallel(Line v)
{
return sgn( (e - s) ^ (v.e - v.s) ) == 0;
}
Point crosspoint(Line v)
{
double a1 = (v.e - v.s) ^ (s - v.s);
double a2 = (v.e - v.s) ^ (e - v.s);
return Point((s.x * a2 - e.x * a1) / (a2 - a1),
(s.y * a2 - e.y * a1) / (a2 - a1));
}
};
struct circle
{
Point p;
double r;
circle(){}
circle(Point a,Point b,Point c)
{
Line u = Line((a + b) / 2,((a + b) / 2) + ((b - a).rotleft()));
Line v = Line((b + c) / 2,((b + c) / 2) + ((c - b).rotleft()));
p = u.crosspoint(v);
r = p.distance(a);
}
int relation(Point b)
{
double dst = b.distance(p);
if(sgn(dst - r) < 0) return 2;
else if(sgn(dst - r) == 0) return 1;
return 0;
}
};
int main(void)
{
int T,n,cnt;
int a,b,c;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
for(int i = 1; i <= n; i++) {
p[i].input();
}
if(n == 1) {
printf("%f %f %f\n",p[1].x - 1,p[1].y,1.0);
}
else if(n > 1 && n <= 4) {
printf("%f %f %f\n", (p[1].x + p[2].x) * 0.5 , (p[1].y + p[2].y) * 0.5,
sqrt( (p[2].x - p[1].x) * (p[2].x - p[1].x) + (p[2].y - p[1].y) * (p[2].y - p[1].y) ) / 2 );
}
else {
while(1) {
a = rand() % n + 1;
b = rand() % n + 1;
c = rand() % n + 1;
Line L1 = Line(p[a],p[b]);
Line L2 = Line(p[a],p[c]);
if(L1.parallel(L2)) {
continue;
}
cnt = 0;
circle O = circle(p[a],p[c],p[b]);
for(int i = 1; i <= n; i++) {
if(O.relation(p[i]) == 1) {
cnt++;
}
}
if(cnt >= ceil(n / 2)) {
printf("%lf %lf %lf\n",O.p.x,O.p.y,O.r);
break;
}
}
}
}
return 0;
}