Geometry Problem

HDU - 6242

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 NN distinct points (Xi,Yi)(Xi,Yi) on the two-dimensional plane. Your task is to find a point PP and a real number RR, such that for at least ⌈N2⌉⌈N2⌉ given points, their distance to point PP is equal to RR.

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)N(1≤N≤105).

The following NN lines describe the points. Each line contains two real numbers XiXiand YiYi (0≤|Xi|,|Yi|≤103)(0≤|Xi|,|Yi|≤103) indicating one give point. It's guaranteed that NN points are distinct.

Output

For each test case, output a single line with three real numbers XP,YP,RXP,YP,R, where (XP,YP)(XP,YP) is the coordinate of required point PP. Three real numbers you output should satisfy 0≤|XP|,|YP|,R≤1090≤|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 RR if it is within an absolute error of 10−310−3 of RR.

Sample Input

1
7
1 1
1 0
1 -1
0 1
-1 1
0 -1
-1 0

Sample Output

0 0 1

题意:

给n个互补相同的二维坐标点,保证可以找到一个点\(p(x,y)\),满足存在\(ceil(n/2)\) 个点和这个点p的距离相同。

思路:

当n=1时,p可以为任意一点

\(2<=n<=4\) 时,取任意两点的中点即可,

当n>=5 时,

我们随机3个互补相同的点,并找到以这3个点确定的圆的圆心以及半径R,然后计算有多少个点和这个圆心的距离为R,如果个数*2>=n,就说明该圆心就是要找的点,半径就是距离。

为什么这样可以?

因为保证一定存在解,那么一定有至少\(ceil(n/2)\) 个点在同一个圆上,那么找到3个点都在这个圆上的概率大概就是\((1/2)^3\) 那么期望大概就是8次就可以确定出圆心。

ac代码

#include<bits/stdc++.h>
#include<ctime>
using namespace std;
typedef long long ll;
typedef double ld;
const ld eps = 1e-6;

int sgn(ld x)
{
    if(fabs(x)<eps)
        return 0;
    if(x<0)
        return -1;
    else
    {
        return 1;
    }
}
struct point
{
    ld x,y;
    point(){}
    point(ld _x,ld _y)
    {
        x=_x;
        y=_y;
    }
    point operator - (const point &b) const
    {
        return point(x-b.x,y-b.y);
    }
    ld operator ^ (const point &b) const
    {
        return x*b.y-y*b.x;
    }
    ld operator * (const point &b) const
    {
        return x*b.x+y*b.y;
    }

};
point getpoint(point a,point b,point c,point d)
{
    point res;
    ld a1,b1,c1,a2,b2,c2;
    a1=a.y-b.y,b1=b.x-a.x,c1=a.x*b.y-b.x*a.y;
    a2=c.y-d.y,b2=d.x-c.x,c2=c.x*d.y-d.x*c.y;
    res.x=(b1*c2-b2*c1)/(a1*b2-a2*b1);
    res.y=-(a1*c2-a2*c1)/(a1*b2-a2*b1);
    return res;
}
struct line
{
    point s,e;
    line(){}
    line(point _s,point _e)
    {
        s=_s;
        e=_e;
    }
    pair<int,point> operator & (const line &b)const
    {
        point res=s;
        if(sgn((s-e)^(b.s-b.e))==0)
        {
            if(sgn((s-b.e)^(b.s-b.e))==0)
            {
                return make_pair(0,res);
            }else{
                return make_pair(1,res);
            }
        }
        res = getpoint(s,e,b.s,b.e);
        return make_pair(2,res);
    }
};

int t;
int n;
point a[100010];
ld R;
line l1,l2;
ld base=2e9;
line getline_(point aa,point bb)
{
    ld xc=bb.x-aa.x;
    ld yc=bb.y-aa.y;
    if(sgn(yc)==0)
    {
        return line(point(bb.x,base),point(bb.x,-base));
    }else
    {
        ld k=-1*xc/yc;
        point mid=point((aa.x+bb.x)*0.5,(aa.y+bb.y)*0.5);
        return line(point(mid.x+base,mid.y+base*k),point(mid.x-base,mid.y-base*k));
    }
}
ld getdis(point aa,point bb)
{
    return sqrt((aa.x-bb.x)*(aa.x-bb.x)+(aa.y-bb.y)*(aa.y-bb.y));
}
point c;
bool check(point aa,point bb,point cc)
{
    l1=getline_(aa,bb);
    l2=getline_(bb,cc);
    pair<int,point> res=l1&l2;
    if(res.first!=2)
    {
        return 0;
    }else if(res.first==2)
    {
        c=res.second;
        R=getdis(c,aa);
        int cnt=0;
        for(int i=1;i<=n;++i)
        {
            if(sgn(fabs(getdis(c,a[i]))-R)==0)
            {
//                cout<<getdis(c,a[i])<<endl;
                cnt++;
            }
        }
//        cout<<" cnt "<<" "<<cnt<<endl;
        return cnt*2>=n;
    }
}
//#define mp make_pair
//
//map<pair<int,pair<int,int> >,bool > vis;
int main()
{
//    ios::sync_with_stdio(false);
//    cin>>t;
    int x,y;
    scanf("%d",&t);
    while(t--)
    {
//        vis.clear();
        std::mt19937 rnd(time(NULL));
//        cin>>n;
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%lf %lf",&a[i].x,&a[i].y);
//            cin>>a[i].x>>a[i].y;
        }
        if(n==1)
        {
            c.x=0;
            c.y=0;
            R=getdis(c,a[1]);
        }else if(n<=4)
        {
            c=point((a[1].x+a[2].x)*0.5,(a[1].y+a[2].y)*0.5);
            R=getdis(c,a[1]);
        }else
        {
            while(1)
            {
                int id1,id2,id3;
                id1=rnd()%n+1;
                do
                {
                    id2=rnd()%n+1;
                }while(id2==id1);
                do
                {
                    id3=rnd()%n+1;
                }while(id3==id1||id3==id2);
    //            cout<<id1<<" "<<id2<<" "<<id3<<endl;
                if(check(a[id1],a[id2],a[id3]))
                {
                    break;
                }
            }
        }
        printf("%.5f %.5f %.5f\n",c.x+eps,c.y+eps,R);
//        cout<<fixed<<setprecision(5)<<c.x+eps<<" "<<c.y+eps<<" "<<R<<endl;
    }
    return 0;
}