zoukankan      html  css  js  c++  java
  • SPOJ CIRU

    CIRU - The area of the union of circles

    no tags 

    You are given N circles and expected to calculate the area of the union of the circles !

    Input

    The first line is one integer n indicates the number of the circles. (1 <= n <= 1000)

    Then follows n lines every line has three integers

    Xi Yi Ri

    indicates the coordinate of the center of the circle, and the radius. (|Xi|. |Yi|  <= 1000, Ri <= 1000)

    Note that in this problem Ri may be 0 and it just means one point !

    Output

    The total area that these N circles with 3 digits after decimal point

    Example

    Input:
    3
    0 0 1
    0 0 1
    100 100 1


    Output:
    6.283
    代码详解见 : http://www.cnblogs.com/oyking/p/3424999.html
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <string>
    #include <map>
    #include <stack>
    #include <queue>
    #include <vector>
    #define inf 0x3f3f3f3f
    #define met(a,b) memset(a,b,sizeof a)
    #define pb push_back
    typedef long long ll;
    using namespace std;
    const int N = 1e5+5;
    const int M = 24005;
    const double PI = acos(-1.0);
    const double EPS = 1e-8;
    
    inline int sgn(double x) {
        return (x > EPS) - (x < -EPS);
    }
    
    struct Point {
        double x, y;
        Point() {}
        Point(double x, double y): x(x), y(y) {}
        void read() {
            scanf("%lf%lf", &x, &y);
        }
        double angle() {
            return atan2(y, x);
        }
        Point operator + (const Point &rhs) const {
            return Point(x + rhs.x, y + rhs.y);
        }
        Point operator - (const Point &rhs) const {
            return Point(x - rhs.x, y - rhs.y);
        }
        Point operator * (double t) const {
            return Point(x * t, y * t);
        }
        Point operator / (double t) const {
            return Point(x / t, y / t);
        }
        double length() const {
            return sqrt(x * x + y * y);
        }
        Point unit() const {
            double l = length();
            return Point(x / l, y / l);
        }
    };
    
    double cross(const Point &a, const Point &b) {
        return a.x * b.y - a.y * b.x;
    }
    
    double dist(const Point &p1, const Point &p2) {
        return (p1 - p2).length();
    }
    
    Point rotate(const Point &p, double angle, const Point &o = Point(0, 0)) {
        Point t = p - o;
        double x = t.x * cos(angle) - t.y * sin(angle);
        double y = t.y * cos(angle) + t.x * sin(angle);
        return Point(x, y) + o;
    }
    
    struct Region {
        double st, ed;
        Region() {}
        Region(double st, double ed): st(st), ed(ed) {}
        bool operator < (const Region &rhs) const {
            if(sgn(st - rhs.st)) return st < rhs.st;
            return ed < rhs.ed;
        }
    };
    
    struct Circle {
        Point c;
        double r;
        vector<Region> reg;
        Circle() {}
        Circle(Point c, double r): c(c), r(r) {}
        void read() {
            c.read();
            scanf("%lf", &r);
        }
        void add(const Region &r) {
            reg.push_back(r);
        }
        bool contain(const Circle &cir) const {
            return sgn(dist(cir.c, c) + cir.r - r) <= 0;
        }
        bool intersect(const Circle &cir) const {
            return sgn(dist(cir.c, c) - cir.r - r) < 0;
        }
    };
    
    double sqr(double x) {
        return x * x;
    }
    
    void intersection(const Circle &cir1, const Circle &cir2, Point &p1, Point &p2) {
        double l = dist(cir1.c, cir2.c);
        double d = (sqr(l) - sqr(cir2.r) + sqr(cir1.r)) / (2 * l);
        double d2 = sqrt(sqr(cir1.r) - sqr(d));
        Point mid = cir1.c + (cir2.c - cir1.c).unit() * d;
        Point v = rotate(cir2.c - cir1.c, PI / 2).unit() * d2;
        p1 = mid + v, p2 = mid - v;
    }
    
    Point calc(const Circle &cir, double angle) {
        Point p = Point(cir.c.x + cir.r, cir.c.y);
        return rotate(p, angle, cir.c);
    }
    
    const int MAXN = 1010;
    
    Circle cir[MAXN];
    bool del[MAXN];
    int n;
    
    double solve() {
        double ans = 0;
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j) if(!del[j]) {
                if(i == j) continue;
                if(cir[j].contain(cir[i])) {
                    del[i] = true;
                    break;
                }
            }
        }
        for(int i = 0; i < n; ++i) if(!del[i]) {
            Circle &mc = cir[i];
            Point p1, p2;
            bool flag = false;
            for(int j = 0; j < n; ++j) if(!del[j]) {
                if(i == j) continue;
                if(!mc.intersect(cir[j])) continue;
                flag = true;
                intersection(mc, cir[j], p1, p2);
                double rs = (p2 - mc.c).angle(), rt = (p1 - mc.c).angle();
                if(sgn(rs) < 0) rs += 2 * PI;
                if(sgn(rt) < 0) rt += 2 * PI;
                if(sgn(rs - rt) > 0) mc.add(Region(rs, PI * 2)), mc.add(Region(0, rt));
                else mc.add(Region(rs, rt));
            }
            if(!flag) {
                ans += PI * sqr(mc.r);
                continue;
            }
            sort(mc.reg.begin(), mc.reg.end());
            int cnt = 1;
            for(int j = 1; j < int(mc.reg.size()); ++j) {
                if(sgn(mc.reg[cnt - 1].ed - mc.reg[j].st) >= 0) {
                    mc.reg[cnt - 1].ed = max(mc.reg[cnt - 1].ed, mc.reg[j].ed);
                } else mc.reg[cnt++] = mc.reg[j];
            }
            mc.add(Region());
            mc.reg[cnt] = mc.reg[0];
            for(int j = 0; j < cnt; ++j) {
                p1 = calc(mc, mc.reg[j].ed);
                p2 = calc(mc, mc.reg[j + 1].st);
                ans += cross(p1, p2) / 2;
                double angle = mc.reg[j + 1].st - mc.reg[j].ed;
                if(sgn(angle) < 0) angle += 2 * PI;
                ans += 0.5 * sqr(mc.r) * (angle - sin(angle));
            }
        }
        return ans;
    }
    
    int main() {
        scanf("%d", &n);
        for(int i = 0; i < n; ++i) cir[i].read();
        printf("%.3f
    ", solve() + EPS);
    }
  • 相关阅读:
    Hadoop 集群搭建步骤
    Linux 常见的命令
    Mysql 的事物理解
    数据库的理论知识
    IDEA debug
    junit 测试
    Mysql 索引的知识
    JSON解析
    java 多线程
    Java集合框架关系图
  • 原文地址:https://www.cnblogs.com/jianrenfang/p/6490795.html
Copyright © 2011-2022 走看看