• SPOJ 8073 The area of the union of circles (圆并入门)


    Sphere Online Judge (SPOJ) - Problem CIRU

    【求圆并的若干种算法,圆并扩展算法】_AekdyCoin的空间_百度空间

      参考AekdyCoin的圆并算法解释,根据理解写出的代码。圆并这么多题中,最基础一题。

      操作如下:

    (1)对一个圆,获得所有与其他圆的交点作为时间戳。

      a.如果这个圆不被其他任何圆覆盖,这个圆直接保留。

      b.如果Case中有两个完全重合的圆,可以保留标号小(或大)的圆,也只保留这一个。

    (2)每经过一个时间戳就对计数器加减,如果计数器从0变1,加上这段圆弧和对应的三角形。

    (3)所有这样的圆独立计算,最后求出的面积累加即可。

    代码如下(1y):

      1 #include <cmath>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <iomanip>
      5 #include <iostream>
      6 #include <algorithm>
      7 
      8 using namespace std;
      9 
     10 const double PI = acos(-1.0);
     11 const double EPS = 1e-8;
     12 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
     13 template<class T> T sqr(T x) { return x * x;}
     14 typedef pair<double, double> Point;
     15 #define x first
     16 #define y second
     17 Point operator + (Point a, Point b) { return Point(a.x + b.x, a.y + b.y);}
     18 Point operator - (Point a, Point b) { return Point(a.x - b.x, a.y - b.y);}
     19 Point operator * (Point a, double p) { return Point(a.x * p, a.y * p);}
     20 Point operator / (Point a, double p) { return Point(a.x / p, a.y / p);}
     21 
     22 inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;}
     23 inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;}
     24 inline double angle(Point a) { return atan2(a.y, a.x);}
     25 inline double veclen(Point a) { return sqrt(dot(a, a));}
     26 
     27 struct Circle {
     28     Point c;
     29     double r;
     30     Circle() {}
     31     Circle(Point c, double r) : c(c), r(r) {}
     32     Point point(double p) { return Point(c.x + r * cos(p), c.y + r * sin(p));}
     33     void get() { scanf("%lf%lf%lf", &c.x, &c.y, &r);}
     34 } ;
     35 
     36 bool ccint(Circle a, Circle b, double &a1, double &a2) { // ips for Circle-a (anti-clockwise p1->p2)
     37     double d = veclen(a.c - b.c);
     38     double r1 = a.r, r2 = b.r;
     39     if (sgn(d - r1 - r2) >= 0) return 0;
     40     if (sgn(fabs(r1 - r2) - d) >= 0) return 0;
     41     double da = acos((sqr(d) + sqr(r1) - sqr(r2)) / (2 * d * r1));
     42     double ang = angle(b.c - a.c);
     43     a1 = ang - da, a2 = ang + da;
     44     return 1;
     45 }
     46 
     47 const int N = 1111;
     48 Circle cir[N];
     49 
     50 inline double gettri(Point o, Point a, Point b) { return cross(a - o, b - o) / 2;}
     51 inline double getarc(Circle o, double a, double b) { return (b - a) * sqr(o.r) / 2 - gettri(o.c, o.point(a), o.point(b));}
     52 
     53 typedef pair<double, int> Event;
     54 Event ev[N << 2];
     55 
     56 bool inside(int a, int n) {
     57     double d, r1, r2;
     58     for (int i = 0; i < n; i++) {
     59         if (i == a) continue;
     60         d = veclen(cir[i].c - cir[a].c);
     61         r1 = cir[i].r, r2 = cir[a].r;
     62         if (sgn(r1 - r2) == 0 && sgn(fabs(r1 - r2) - d) == 0) {
     63             if (i > a) return 1;
     64             continue;
     65         }
     66         if (sgn(r1 - r2) >= 0 && sgn(fabs(r1 - r2) - d) >= 0) return 1;
     67     }
     68     return 0;
     69 }
     70 
     71 double getarea(int a, int n) {
     72     if (inside(a, n)) return 0;
     73     Circle &c = cir[a];
     74     double ret = 0;
     75     double a1, a2;
     76     Point p1, p2;
     77     int tt = 0;
     78     for (int i = 0; i < n; i++) {
     79         if (i == a) continue;
     80         if (ccint(c, cir[i], a1, a2)) {
     81             if (a2 > PI) ev[tt++] = Event(a1, 1), ev[tt++] = Event(PI, -1), ev[tt++] = Event(-PI, 1), ev[tt++] = Event(a2 - 2 * PI, -1);
     82             else if (a1 < -PI) ev[tt++] = Event(a1 + 2 * PI, 1), ev[tt++] = Event(PI, -1), ev[tt++] = Event(-PI, 1), ev[tt++] = Event(a2, -1);
     83             else ev[tt++] = Event(a1, 1), ev[tt++] = Event(a2, -1);
     84         }
     85     }
     86     if (tt == 0) return PI * sqr(c.r);
     87     sort(ev, ev + tt);
     88     int cnt = 0;
     89     double last = -PI;
     90     for (int i = 0; i < tt; i++) {
     91         double cur = ev[i].x;
     92         if (ev[i].y == 1 && cnt == 0) ret += getarc(c, last, cur) + cross(c.point(last), c.point(cur)) / 2;
     93         cnt += ev[i].y;
     94         last = cur;
     95     }
     96     ret += getarc(c, last, PI) + cross(c.point(last), c.point(PI)) / 2;
     97     return ret;
     98 }
     99 
    100 double work(int n) {
    101     double ret = 0;
    102     for (int i = 0; i < n; i++) ret += getarea(i, n);
    103     return ret;
    104 }
    105 
    106 int main() {
    107     int n;
    108     while (~scanf("%d", &n)) {
    109         for (int i = 0; i < n; i++) cir[i].get();
    110         printf("%.3f
    ", work(n));
    111     }
    112     return 0;
    113 }
    View Code

    ——written by Lyon

  • 相关阅读:
    iOS-Core-Animation-Advanced-Techniques(一)
    vue 路由
    Vue 生产环境部署
    vue 单文件组件
    vue 插件
    Vue 混合
    vue 自定义指令
    vue render函数 函数组件化
    vue render函数
    vue 过渡状态
  • 原文地址:https://www.cnblogs.com/LyonLys/p/spoj_ciru_Lyon.html
Copyright © 2020-2023  润新知