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): 772
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.

 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

2017中国大学生程序设计竞赛-哈尔滨站-重现赛(感谢哈理工)

题意:给出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;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值