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);
    }
  • 相关阅读:
    STL源码剖析之_allocate函数
    PAT 1018. Public Bike Management
    PAT 1016. Phone Bills
    PAT 1012. The Best Rank
    PAT 1014. Waiting in Line
    PAT 1026. Table Tennis
    PAT 1017. Queueing at Bank
    STL源码剖析之list的sort函数实现
    吃到鸡蛋好吃,看看是哪只母鸡下的蛋:好用的Sqlite3
    cJSON
  • 原文地址:https://www.cnblogs.com/jianrenfang/p/6490795.html
Copyright © 2011-2022 走看看