HDU - 6242 Geometry Problem 随机数

题目链接:https://vjudge.net/problem/HDU-6242

题意:n个点,找到一个圆,满足圆上点的数目大于等于⌈N / 2⌉

题解:三个不在一条直线上的点确定一个圆,随机到圆上点的概率是1 / 2,那么三次就是1 / 8,所以如果随机找出三个点,那么找到这个圆的期望次数就是8次

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const double eps = 1e-8;
int n;
int sgn(double x) {
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    return 1;
}
struct Point {
    double x, y;
    Point(){}
    Point(double x_, double y_) {
        x = x_;
        y = y_;
    }
    
    Point rotleft() {
        return Point(-y, x);
    }
    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;
    }
    double distance(Point p) {
        return hypot(x - p.x, y-p.y);
    }
}P[N];
struct Line {
    Point s, e;
    Line(){}
    Line(Point s_, Point e_) {
        s = s_;
        e = e_;
    }
    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 p_, double r_) {
        p = p_;
        r = r_;
    }
    void get1(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);
    }
    bool relation(Point b) {
        double dst = b.distance(p);
        if(sgn(dst - r) == 0) return 1;
        return 0;
    }
};
int main() {
    int T;
    int n;
    int x, y, z;
    
    circle C;
    int cnt = 0;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%lf %lf", &P[i].x, &P[i].y);
        if(n == 1) {
        	printf("%f %f %f\n", P[1].x - 1, P[1].y, 1.0);
        	continue;
		}
		if(n <= 4) {
			printf("%.3f %.3f %.3f\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);
			continue;
		}
        for(int i = 1; ; i++) {
            x = rand() % n + 1;
            y = rand() % n + 1;
            z = rand() % n + 1;
            if( sgn((P[x] - P[y]) ^ (P[x] - P[z])) == 0) continue;
            C.get1(P[x], P[y], P[z]);
            cnt = 0;
            for(int j = 1; j <= n; j++) {
                if(C.relation(P[j])) cnt++;
            }
            if(cnt >= (n + 1) / 2) {
                printf("%lf %lf %lf\n", C.p.x, C.p.y, C.r);
                break;
            }
        }

    }
    return 0;
}
/*
7
1 1
1 0
1 -1
0 1
-1 1
0 -1 
-1 0
*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值