hdu 6242 Geometry Problem(随机化+三点求外接圆)

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值