Hdu-6242 2017CCPC-哈尔滨站 M.Geometry Problem 计算几何 随机

题面

题意:给你n个点,让你找到一个圆,输出圆心,和半径,使得有超过一半的点刚好在圆上.n<=1e5,题目保证了有解

题解:刚开始看着很不可做的样子,但是多想想,三点确定一个圆,三点啊!

        现在有1/2的点都在圆上,意味着很多选出来的3个点都会导致同样的结果啊

        我们同时可以说,每次随机一个点,这个点在圆上的概率为1/2,那任意三个点同时在圆上的概率就是1/8

        所以我们随机来个几万次就好了啊!

       注意的就是点数<=4的时候,1的时候输出自己就可以了,2,3,4的时候随便输出2个点的中点就行了

     

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 struct point
 4 {
 5     double x,y;
 6 }a[100005],pp;
 7 int T,n,x,y,z;
 8 #define eps 1e-10
 9 double R;
10 point cit(point a,point b,point c)
11 {
12     point cp;
13     double a1=b.x-a.x,b1=b.y-a.y,c1=(a1*a1+b1*b1)/2;
14     double a2=c.x-a.x,b2=c.y-a.y,c2=(a2*a2+b2*b2)/2;
15     double d=a1*b2-a2*b1;
16     cp.x=a.x+(c1*b2-c2*b1)/d;
17     cp.y=a.y+(a1*c2-a2*c1)/d;
18     return cp;
19 }
20 double dis(point a,point b)
21 {
22     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
23 }
24 int ok(point p)
25 {
26     int tot=0;
27     for (int i=1;i<=n;i++)
28     {
29         if (fabs(dis(p,a[i])-R)<eps) tot++;
30         if (tot>=(n+1)/2) return 1;
31     }
32     return 0;
33 }
34 int kk(point x,point y,point z)
35 {
36     if ((x.x-y.x)*(x.y-z.y)==(x.y-y.y)*(x.x-z.x)) return 1;
37     return 0;
38 }
39 int main()
40 {
41     srand(time(0));
42     scanf("%d",&T);
43     while (T--)
44     {
45         scanf("%d",&n);
46         for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
47         if (n==1)
48         {
49             printf("%lf %lf 0\n",a[1].x,a[1].y);
50             continue;
51         } 
52         if (n<=4)
53         {
54             pp.x=(a[1].x+a[2].x)/2;
55             pp.y=(a[1].y+a[2].y)/2;
56             printf("%lf %lf %lf\n",pp.x,pp.y,dis(pp,a[1]));
57             continue;
58         }
59         for (int i=1;i<=5000000;i++)
60         {
61             x=rand()*rand()%n+1;
62             y=rand()*rand()%n+1;
63             z=rand()*rand()%n+1;
64             if (x==y || y==z || x==z) continue;
65             if (kk(a[x],a[y],a[z])) continue;
66             pp=cit(a[x],a[y],a[z]);
67             R=dis(pp,a[x]);
68             if (ok(pp))
69             {
70                 printf("%lf %lf %lf\n",pp.x,pp.y,R);
71                 break;
72             }
73         }
74     }
75 }

 

转载于:https://www.cnblogs.com/qywhy/p/9748389.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值