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);
}
原文地址:https://www.cnblogs.com/jianrenfang/p/6490795.html