HDU 6242 Geometry Problem(计算几何 + 随机化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6242

思路:当 n == 1 时 任取一点 p 作为圆心即可。

    n >= 2 && n < 5 时 此时有可能出现所有点共线,所以取任意俩点间中点作为圆的圆心。

    n >= 5 保证了有解。所以不可能有所有点共线的情况,随机取三个点在正解圆上的概率是 1/8,还是蛮大的...。

    外学了下随机算法的写法....时间种子 time(0)要强制转成int,不然会WA,不造为啥....

AC代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const double eps = 1e-4;
  4 const double INF = 1e18;
  5 const int maxn = 1e5 + 5;
  6 int sgn(double x)
  7 {
  8     if(fabs(x) < eps) return 0;
  9     else return x < 0 ? -1 : 1;
 10 }
 11 struct Point{
 12     double x, y;
 13     Point(){}
 14     Point(double _x, double _y){
 15         x = _x; y = _y;
 16     }
 17     void input()
 18     {
 19         scanf("%lf %lf", &x, &y);
 20     }
 21     bool operator ==(const Point &b) const{
 22         return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
 23     }
 24     bool operator <(const Point &b) const{
 25         return sgn(x - b.x) == 0 ? sgn(y - b.y) < 0 : x < b.x;
 26     }
 27     Point operator -(const Point &b) const{
 28         return Point(x - b.x, y - b.y);
 29     }
 30     Point operator +(const Point &b) const{
 31         return Point(x + b.x, y + b.y);
 32     }
 33     double operator ^(const Point &b) const{
 34         return x*b.y - b.x*y;
 35     }
 36     double operator *(const Point &b) const{
 37         return x*b.x + y*b.y;
 38     }
 39     Point operator*(const double &k)const{
 40         return Point(x*k,y*k);
 41     }
 42     Point operator/(const double &k)const{
 43         return Point(x/k,y/k);
 44     }
 45     Point rotleft(){
 46         return Point(-y, x);
 47     }
 48     double distance(Point p)
 49     {
 50         return hypot(x - p.x,y - p.y);
 51     }
 52 } p[maxn];
 53 struct Line{
 54     Point s, e;
 55     Line(){}
 56     Line(Point _s, Point _e){
 57         s = _s, e = _e;
 58     }
 59     Point crosspoint(Line v){
 60         double a1 = (v.e - v.s) ^ (s - v.s);
 61         double a2 = (v.e - v.s) ^ (e - v.s);
 62         return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
 63     }
 64 };
 65 struct circle{
 66     Point p;
 67     double r;
 68     circle(){}
 69     circle(Point a, Point b, Point c){
 70         Line u = Line( (a + b) / 2, ( (a + b) / 2) + ( (b - a).rotleft() ));
 71         Line v = Line( (b + c) / 2, ( (b + c) / 2) + ( (c - b).rotleft() ));
 72         p = u.crosspoint(v);
 73         r = p.distance(a);
 74     }
 75     int relation(Point b){
 76         double dst = b.distance(p);
 77         if(sgn(dst - r)<0) return 2;
 78         else if(sgn(dst - r) == 0) return 1;
 79         return 0;
 80     }
 81 };
 82 int main()
 83 {
 84     int t;
 85     scanf("%d",&t);
 86     srand((int)time(0));
 87     while(t--)
 88     {
 89         int n;
 90         scanf("%d",&n);
 91         for(int i = 0;i < n;i++) p[i].input();
 92         if(n == 1) printf("0.000 0.000 %.6f\n",p[0].distance(Point(0,0)));
 93         else if(n >= 2 && n < 5){
 94             Point v = (p[0] + p[1])/2;
 95             printf("%.6f %.6f %.6f\n", v.x, v.y, 0.5*p[0].distance(p[1]));
 96         }
 97         else{
 98             while(1){
 99                 int a = rand() % n, b = a, c = a;
100                 while(b = rand() % n){
101                     if(b != a) break;
102                 }
103                 while(c = rand() % n){
104                     if(c != a && c != b) break;
105                 }
106                 circle C = circle(p[a], p[b], p[c]);
107                 int num = 0;
108                 for(int i = 0;i < n;i++)
109                 {
110                     if(C.relation(p[i]) == 1) num++;
111                 }
112                 if(num >= (n + 1) / 2){
113                     printf("%.6f %.6f %.6f\n",C.p.x ,C.p.y, C.r);
114                     break;
115                 }
116             }
117         }
118     }
119     return 0;
120 }

原文地址:https://www.cnblogs.com/Carered/p/11568666.html

时间: 2024-10-11 04:57:51

HDU 6242 Geometry Problem(计算几何 + 随机化)的相关文章

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

题面 题意:给你n个点,让你找到一个圆,输出圆心,和半径,使得有超过一半的点刚好在圆上.n<=1e5,题目保证了有解 题解:刚开始看着很不可做的样子,但是多想想,三点确定一个圆,三点啊! 现在有1/2的点都在圆上,意味着很多选出来的3个点都会导致同样的结果啊 我们同时可以说,每次随机一个点,这个点在圆上的概率为1/2,那任意三个点同时在圆上的概率就是1/8 所以我们随机来个几万次就好了啊! 注意的就是点数<=4的时候,1的时候输出自己就可以了,2,3,4的时候随便输出2个点的中点就行了 1 #

HDU - 6242:Geometry Problem(随机+几何)

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

hdoj 1086 You can Solve a Geometry Problem too 【计算几何】

题意:就是判断各线段之间有没有交点. 判断两线段相交,要运用到叉积.两个线段相交肯定相互跨越,假设一个条线段(p1p2),另一条是(q1q2),那么p1p2肯定在q1q2线段的两侧,那么运用叉积如果p1p2跨越q1q2的话(q1p1)x(q2p2)<= 0.同样也要验证 q1q2是不是也跨越p1p2,注意:p1p2跨越q1q2,不代两个线段相交,可能是p1p2跨越直线q1q2,所以说还是要再次判断q1q2是不是跨越p1p2 还有另外一种比较容易理解的解法: 就是如果两个线段相交,那么两线段两端端

HDU 1086 You can Solve a Geometry Problem too(判断线段相交)

题目地址:HDU 1086 就这么一道仅仅判断线段相交的题目写了2k多B的代码..是不是有点浪费...但是我觉得似乎哪里也优化不了了.... 判断线段相交就是利用的叉积.假如现在两条线段分别是L1和L2,先求L1和L2两个端点与L1的某个端点的向量的叉积,如果这两个的叉积的乘积小于0的话,说明L1在是在L2两个端点之间的,但此时并不保证一定相交.此时需要用同样的方法去判断L2是否在L1的两个端点之间,如果L2也在L1的两个端点之间的话,那就足以说明L1与L2相交.但是这题还需要判断是否端点也相交

HDU 1086:You can Solve a Geometry Problem too

You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6997    Accepted Submission(s): 3385 Problem Description Many geometry(几何)problems were designed in the ACM/

hdu 1086 You can Solve a Geometry Problem too (几何)

You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6932    Accepted Submission(s): 3350 Problem Description Many geometry(几何)problems were designed in the ACM/I

hdu 1086 You can Solve a Geometry Problem too(求线段相交点个数 模板)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1086 ---------------------------------------------------------------------------------------------------------------------------------------------------------- 欢迎光临天资小屋:http://user.qzone.qq.com/593830943

HDU1086 You can Solve a Geometry Problem too(计算几何)

You can Solve a Geometry Problem too                                         Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)                                         Problem Description Many geometry(几何)problems wer

(hdu 7.1.2)You can Solve a Geometry Problem too(求n条线段中,线段两两相交的数量)

题目: You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 145 Accepted Submission(s): 100   Problem Description Many geometry(几何)problems were designed in the ACM/IC