[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 }