Description

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

 

题目大意:求n个圆覆盖的总面积。

思路:参考http://hi.baidu.com/aekdycoin/item/b8ff6adc73c0e71dd78ed0d6

时间复杂度O(n^2*log(n))

 

代码(0.04S):

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <cmath>
  6 #include <vector>
  7 using namespace std;
  8 typedef long long LL;
  9 
 10 const double PI = acos(-1.0);
 11 const double EPS = 1e-8;
 12 
 13 inline int sgn(double x) {
 14     return (x > EPS) - (x < -EPS);
 15 }
 16 
 17 struct Point {
 18     double x, y;
 19     Point() {}
 20     Point(double x, double y): x(x), y(y) {}
 21     void read() {
 22         scanf("%lf%lf", &x, &y);
 23     }
 24     double angle() {
 25         return atan2(y, x);
 26     }
 27     Point operator + (const Point &rhs) const {
 28         return Point(x + rhs.x, y + rhs.y);
 29     }
 30     Point operator - (const Point &rhs) const {
 31         return Point(x - rhs.x, y - rhs.y);
 32     }
 33     Point operator * (double t) const {
 34         return Point(x * t, y * t);
 35     }
 36     Point operator / (double t) const {
 37         return Point(x / t, y / t);
 38     }
 39     double length() const {
 40         return sqrt(x * x + y * y);
 41     }
 42     Point unit() const {
 43         double l = length();
 44         return Point(x / l, y / l);
 45     }
 46 };
 47 
 48 double cross(const Point &a, const Point &b) {
 49     return a.x * b.y - a.y * b.x;
 50 }
 51 
 52 double dist(const Point &p1, const Point &p2) {
 53     return (p1 - p2).length();
 54 }
 55 
 56 Point rotate(const Point &p, double angle, const Point &o = Point(0, 0)) {
 57     Point t = p - o;
 58     double x = t.x * cos(angle) - t.y * sin(angle);
 59     double y = t.y * cos(angle) + t.x * sin(angle);
 60     return Point(x, y) + o;
 61 }
 62 
 63 struct Region {
 64     double st, ed;
 65     Region() {}
 66     Region(double st, double ed): st(st), ed(ed) {}
 67     bool operator < (const Region &rhs) const {
 68         if(sgn(st - rhs.st)) return st < rhs.st;
 69         return ed < rhs.ed;
 70     }
 71 };
 72 
 73 struct Circle {
 74     Point c;
 75     double r;
 76     vector<Region> reg;
 77     Circle() {}
 78     Circle(Point c, double r): c(c), r(r) {}
 79     void read() {
 80         c.read();
 81         scanf("%lf", &r);
 82     }
 83     void add(const Region &r) {
 84         reg.push_back(r);
 85     }
 86     bool contain(const Circle &cir) const {
 87         return sgn(dist(cir.c, c) + cir.r - r) <= 0;
 88     }
 89     bool intersect(const Circle &cir) const {
 90         return sgn(dist(cir.c, c) - cir.r - r) < 0;
 91     }
 92 };
 93 
 94 double sqr(double x) {
 95     return x * x;
 96 }
 97 
 98 void intersection(const Circle &cir1, const Circle &cir2, Point &p1, Point &p2) {
 99     double l = dist(cir1.c, cir2.c);
100     double d = (sqr(l) - sqr(cir2.r) + sqr(cir1.r)) / (2 * l);
101     double d2 = sqrt(sqr(cir1.r) - sqr(d));
102     Point mid = cir1.c + (cir2.c - cir1.c).unit() * d;
103     Point v = rotate(cir2.c - cir1.c, PI / 2).unit() * d2;
104     p1 = mid + v, p2 = mid - v;
105 }
106 
107 Point calc(const Circle &cir, double angle) {
108     Point p = Point(cir.c.x + cir.r, cir.c.y);
109     return rotate(p, angle, cir.c);
110 }
111 
112 const int MAXN = 1010;
113 
114 Circle cir[MAXN];
115 bool del[MAXN];
116 int n;
117 
118 double solve() {
119     double ans = 0;
120     for(int i = 0; i < n; ++i) {
121         for(int j = 0; j < n; ++j) if(!del[j]) {
122             if(i == j) continue;
123             if(cir[j].contain(cir[i])) {
124                 del[i] = true;
125                 break;
126             }
127         }
128     }
129     for(int i = 0; i < n; ++i) if(!del[i]) {
130         Circle &mc = cir[i];
131         Point p1, p2;
132         bool flag = false;
133         for(int j = 0; j < n; ++j) if(!del[j]) {
134             if(i == j) continue;
135             if(!mc.intersect(cir[j])) continue;
136             flag = true;
137             intersection(mc, cir[j], p1, p2);
138             double rs = (p2 - mc.c).angle(), rt = (p1 - mc.c).angle();
139             if(sgn(rs) < 0) rs += 2 * PI;
140             if(sgn(rt) < 0) rt += 2 * PI;
141             if(sgn(rs - rt) > 0) mc.add(Region(rs, PI * 2)), mc.add(Region(0, rt));
142             else mc.add(Region(rs, rt));
143         }
144         if(!flag) {
145             ans += PI * sqr(mc.r);
146             continue;
147         }
148         sort(mc.reg.begin(), mc.reg.end());
149         int cnt = 1;
150         for(int j = 1; j < int(mc.reg.size()); ++j) {
151             if(sgn(mc.reg[cnt - 1].ed - mc.reg[j].st) >= 0) {
152                 mc.reg[cnt - 1].ed = max(mc.reg[cnt - 1].ed, mc.reg[j].ed);
153             } else mc.reg[cnt++] = mc.reg[j];
154         }
155         mc.add(Region());
156         mc.reg[cnt] = mc.reg[0];
157         for(int j = 0; j < cnt; ++j) {
158             p1 = calc(mc, mc.reg[j].ed);
159             p2 = calc(mc, mc.reg[j + 1].st);
160             ans += cross(p1, p2) / 2;
161             double angle = mc.reg[j + 1].st - mc.reg[j].ed;
162             if(sgn(angle) < 0) angle += 2 * PI;
163             ans += 0.5 * sqr(mc.r) * (angle - sin(angle));
164         }
165     }
166     return ans;
167 }
168 
169 int main() {
170     scanf("%d", &n);
171     for(int i = 0; i < n; ++i) cir[i].read();
172     printf("%.3f\n", solve() + EPS);
173 }
View Code

 


以下转自:http://hi.baidu.com/aekdycoin/item/b8ff6adc73c0e71dd78ed0d6

 

相关文章: