圆并模板

来源:互联网 发布:python 线程同步 编辑:程序博客网 时间:2024/06/07 23:03
#include <cstdio>#include <algorithm>#include <iostream>#include <cmath>using namespace std;const int N = 1100;const double eps = 1e-8, PI = 3.14159265358979;int n;bool v[N];inline double sqr (double x) {return x * x; }inline int dcmp (double x) { return x < -eps ? -1 : x > eps; }struct vec {    double x, y;    vec () {}    vec (double _x, double _y) : x (_x), y (_y) {}    double dot (const vec & a) { return x * a.x + y * a.y; }    double cross (const vec & a) { return x * a.y - y * a.x; }    double len () { return sqrt (x * x + y * y); }    vec pull (double t) {        return vec (x * t, y * t);    }    vec rot (double cos, double sin) {        return vec (x * cos + y * sin, x * -sin + y * cos); }};typedef vec point;inline vec operator - (const point & a, const point & b){    return vec (a.x - b.x, a.y - b.y);}inline point operator + (const point & a, const vec & b){    return point (a.x + b.x, a.y + b.y);}struct Q {    double val;    point A;    int sign;    Q () {}    Q (double _val, const point & _A, int _sign) { val = _val; A = _A; sign = _sign; }    bool operator < (const Q & a) const {        return val < a.val;    }}a[N];typedef pair<Q, Q> pi;#define X first#define Y secondstruct ciru {    double r;    point o;    void scan () { scanf ("%lf%lf%lf", &o.x, &o.y, &r); }    void print () { printf ("%lf %lf %lf\n", o.x, o.y, r); }    double dis (const ciru & a){        return (o - a.o).len ();    }    bool in (const ciru & a){        return dcmp (a.r - r - this->dis (a)) >= 0;    }    bool out (const ciru & a){        return dcmp (this->dis (a) - (a.r + r)) >= 0;    }    pi G (const ciru & a)    {        vec oo = a.o - o;        double d = oo.len ();        double cos = (sqr (r) + sqr (d) - sqr (a.r)) / (2 * r * d);        vec t1 = oo.rot (cos, sqrt (1 - sqr (cos))).pull (r / d);        vec t2 = oo.rot (cos, -sqrt (1 - sqr (cos))).pull (r / d);        double t;        return pi (Q ((t = atan2 (t1.y, t1.x)) < 0 ? t + 2 * PI : t, o + t1, 1),                   Q ((t = atan2 (t2.y, t2.x)) < 0 ? t + 2 * PI : t, o + t2, -1));    }}cir[N];inline bool check (int x){    for (int i = 1; i <= n; i ++)    {        if (i == x || v[i]) continue;        if (cir[x].in (cir[i]))            return true;    }    return false;}inline double area (Q & a, const Q & b, double r){    double t = b.val - a.val;    return 0.5 * sqr (r) * (t - sin (t)) + 0.5 * a.A.cross (b.A);}inline double G (int x){    int cnt = 0, now = 0;double S (0);pi tmp;point O;    a[++ cnt].val = 0;    O = a[cnt].A = cir[x].o + vec (cir[x].r, 0);    a[cnt].sign = 0;    a[++ cnt].val = 2 * PI;    a[cnt].A = O;    a[cnt].sign = 0;    for (int i = 1; i <= n; i ++)    {        if (i == x || cir[x].out (cir[i])) continue;        tmp = cir[x].G (cir[i]);        a[++ cnt] = tmp.X;        a[++ cnt] = tmp.Y;        if (a[cnt - 1].val > a[cnt].val)            a[++ cnt] = Q (0, O, 1), a[++ cnt] = Q (2 * PI, O, -1);    }    sort (a + 1, a + 1 + cnt);    for (int i = 1; i < cnt; i ++)    {        now += a[i].sign;        if (now == 0)            S += area (a[i], a[i + 1], cir[x].r);    }    return S;}int main (){   while(~scanf ("%d", &n))   {    for (int i = 1; i <= n; i ++)        cir[i].scan ();    for (int i = 1; i <= n; i ++)        if (dcmp (cir[i].r) == 0)            v[i] = true;    for (int i = 1; i <= n; i ++)    {        if (v[i]) continue;        v[i] = check (i);    }    for (int i = n; i >= 1; i --)        if (v[i])        {            n --;            for (int j = i + 1; j <= n + 1; j ++)                cir[j - 1] = cir[j];        }    double S (0);    for (int i = 1; i <= n; i ++)        S += G (i);    printf ("%.3lf\n", S);   }    return 0;}

0 0