[SPOJ]CIRU 圆并

存代码

新的编程方法? 基本过程依赖于对象?

View Code
  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <cmath>
  5 using namespace std;
  6 const int N = 1100;
  7 const double eps = 1e-8, PI = 3.14159265358979;
  8 int n;bool v[N];
  9 inline double sqr (double x) {return x * x; }
 10 inline int dcmp (double x) { return x < -eps ? -1 : x > eps; }
 11 struct vec {
 12     double x, y;
 13     vec () {}
 14     vec (double _x, double _y) : x (_x), y (_y) {}
 15 
 16     double dot (const vec & a) { return x * a.x + y * a.y; }
 17     double cross (const vec & a) { return x * a.y - y * a.x; }
 18     double len () { return sqrt (x * x + y * y); }
 19     vec pull (double t) {
 20         return vec (x * t, y * t);
 21     }
 22     vec rot (double cos, double sin) {
 23         //printf ("%lf %lf\n", x * cos + y * sin, x * -sin + y * cos);
 24         return vec (x * cos + y * sin, x * -sin + y * cos); }
 25 };
 26 typedef vec point;
 27 inline vec operator - (const point & a, const point & b)
 28 {
 29     return vec (a.x - b.x, a.y - b.y);
 30 }
 31 inline point operator + (const point & a, const vec & b)
 32 {
 33     return point (a.x + b.x, a.y + b.y);
 34 }
 35 struct Q {
 36     double val;
 37     point A;
 38     int sign;
 39     Q () {}
 40     Q (double _val, const point & _A, int _sign) { val = _val; A = _A; sign = _sign; }
 41     bool operator < (const Q & a) const {
 42         return val < a.val;
 43     }
 44 }a[N];
 45 typedef pair<Q, Q> pi;
 46 #define X first
 47 #define Y second
 48 struct ciru {
 49     double r;
 50     point o;
 51     void scan () { scanf ("%lf%lf%lf", &o.x, &o.y, &r); }
 52     void print () { printf ("%lf %lf %lf\n", o.x, o.y, r); }
 53     double dis (const ciru & a){
 54         return (o - a.o).len ();
 55     }
 56     bool in (const ciru & a){
 57         return dcmp (a.r - r - this->dis (a)) >= 0;
 58     }
 59     bool out (const ciru & a){
 60         return dcmp (this->dis (a) - (a.r + r)) >= 0;
 61     }
 62     pi G (const ciru & a)
 63     {
 64         vec oo = a.o - o;
 65         double d = oo.len ();
 66         double cos = (sqr (r) + sqr (d) - sqr (a.r)) / (2 * r * d);
 67         vec t1 = oo.rot (cos, sqrt (1 - sqr (cos))).pull (r / d);
 68         vec t2 = oo.rot (cos, -sqrt (1 - sqr (cos))).pull (r / d);
 69         //printf ("%lf %lf %lf\n", t1.x, t1.y, atan2 (t1.y, t1.x));
 70         //printf ("%lf %lf %lf\n", t2.x, t2.y, atan2 (t2.y, t2.x));
 71         //puts ("**************************");
 72         double t;
 73         return pi (Q ((t = atan2 (t1.y, t1.x)) < 0 ? t + 2 * PI : t, o + t1, 1), 
 74                    Q ((t = atan2 (t2.y, t2.x)) < 0 ? t + 2 * PI : t, o + t2, -1));
 75     }
 76 }cir[N];
 77 inline bool check (int x)
 78 {
 79     for (int i = 1; i <= n; i ++)
 80     {
 81         if (i == x || v[i]) continue;
 82         if (cir[x].in (cir[i]))
 83             return true;
 84     }
 85     return false;
 86 }
 87 inline double area (Q & a, const Q & b, double r)
 88 {
 89     double t = b.val - a.val;
 90     //printf ("%lf\n", sqr (r) * (t - sin (t)) + a.A.cross (b.A));
 91     return 0.5 * sqr (r) * (t - sin (t)) + 0.5 * a.A.cross (b.A);
 92 }
 93 inline double G (int x)
 94 { 
 95     int cnt = 0, now = 0;double S (0);pi tmp;point O;
 96     a[++ cnt].val = 0;
 97     O = a[cnt].A = cir[x].o + vec (cir[x].r, 0);
 98     a[cnt].sign = 0;
 99     a[++ cnt].val = 2 * PI;
100     a[cnt].A = O;
101     a[cnt].sign = 0;
102     for (int i = 1; i <= n; i ++)
103     {
104         if (i == x || cir[x].out (cir[i])) continue;
105         tmp = cir[x].G (cir[i]);
106         a[++ cnt] = tmp.X;
107         a[++ cnt] = tmp.Y;
108         if (a[cnt - 1].val > a[cnt].val)
109             a[++ cnt] = Q (0, O, 1), a[++ cnt] = Q (2 * PI, O, -1);
110     }
111     sort (a + 1, a + 1 + cnt);
112     for (int i = 1; i < cnt; i ++)
113     {
114         now += a[i].sign;
115         if (now == 0)
116             S += area (a[i], a[i + 1], cir[x].r);
117     }
118     return S;
119 }
120 int main ()
121 {
122     //freopen ("a.in", "r", stdin);
123     //freopen ("a.out", "w", stdout);
124     scanf ("%d", &n);
125     for (int i = 1; i <= n; i ++)
126         cir[i].scan ();
127     for (int i = 1; i <= n; i ++)
128         if (dcmp (cir[i].r) == 0)
129             v[i] = true;
130     for (int i = 1; i <= n; i ++)
131     {
132         if (v[i]) continue;
133         v[i] = check (i);
134     }
135     for (int i = n; i >= 1; i --)
136         if (v[i])
137         {
138             n --;
139             for (int j = i + 1; j <= n + 1; j ++)
140                 cir[j - 1] = cir[j];
141         }
142     /*printf ("%d\n", n);
143     for (int i = 1; i <= n; i ++)
144         cir[i].print ();*/
145     
146     double S (0);
147     for (int i = 1; i <= n; i ++)
148         S += G (i);
149     printf ("%.3lf\n", S);
150     return 0;        
151 }

 

posted @ 2013-02-17 23:23  Moretimes  阅读(811)  评论(0编辑  收藏  举报