简略题意:给出n个圆,求他们的面积并。
- 去掉内含圆,因为不会对答案造成影响。
- 去掉和其他圆都相离的圆,这部分答案直接计算。
这样我们就只用计算和别的圆相交的圆的面积了。 - 辛普森积分暴力搞吧,对于x = a的直线,看多少圆覆盖了这条直线,求出这部分的长度即可。
#define poj
#ifdef poj
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
const double pi = acos(-1.0);
typedef long long LL;
typedef unsigned long long ULL;
void umax(int &a, int b) {
a = max(a, b);
}
void umin(int &a, int b) {
a = min(a, b);
}
void file() {
freopen("a.in", "r", stdin);
// freopen("1.txt", "w", stdout);
}
namespace Solver {
int n;
struct point {
double x, y;
};
struct cir {
point o;
double r;
bool operator < (const cir & b) const {
return r < b.r;
}
} c[1111];
vector<cir> G, V;
bool tag[1111];
double dis(point a, point b) {
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool is_covered(cir a, cir b) {
return dis(a.o, b.o) + a.r <= b.r;
}
bool is_apart(cir a, cir b) {
return dis(a.o, b.o) > a.r + b.r;
}
struct Itv {
double l, r;
bool operator < (const Itv & x) const {
return l < x.l || (l == x.l && r < x.r);
}
};
double F(double x) {
vector<Itv> R;
double sum = 0;
for(int i = 0; i < V.size(); i++) {
if(x >= V[i].o.x - V[i].r && x <= V[i].o.x + V[i].r) {
double len = sqrt(V[i].r*V[i].r-(V[i].o.x-x)*(V[i].o.x-x));
R.push_back({V[i].o.y - len, V[i].o.y + len});
}
}
sort(all(R));
double pre = -1e20;
for(int i = 0; i < R.size(); i++) {
pre = max(pre, R[i].l);
sum += max(0.0, R[i].r - pre);
pre = max(pre, R[i].r);
}
return sum;
}
double simpson(double a, double b) {
double c = a + (b - a) / 2;
return (F(a) + 4 * F(c) + F(b))*(b - a) / 6;
}
double asr(double a, double b, double eps, double A) {
double c = a + (b - a) / 2;
double L = simpson(a, c), R = simpson(c, b);
if (fabs(L + R - A) <= 15 * eps)return L + R + (L + R - A) / 15.0;
return asr(a, c, eps / 2, L) + asr(c, b, eps / 2, R);
}
double asr(double a, double b, double eps) {
return asr(a, b, eps, simpson(a, b));
}
void solve() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
double x, y, r;
scanf("%lf%lf%lf", &x, &y, &r);
c[i] = {x, y, r};
}
sort(c + 1, c + 1 + n);
for(int i = 1; i <= n; i++)
for(int j = i + 1; j <= n; j++) {
if(is_covered(c[i], c[j]))
tag[i] = 1;
}
double ans = 0;
for(int i = 1; i <= n; i++)
if(!tag[i]) G.push_back(c[i]);
memset(tag, 0, sizeof tag);
for(int i = 0; i < G.size(); i++) {
int cnt = 0;
for(int j = 0; j < G.size(); j++)
cnt += is_apart(G[i], G[j]);
if(cnt == G.size() - 1)
ans += G[i].r*G[i].r*pi, tag[i] = 1;
}
for(int i = 0; i < G.size(); i++)
if(tag[i] == 0) V.push_back(G[i]);
printf("%.3f\n", asr(-2000, 2000, 1e-6) + ans);
}
};
int main() {
// file();
Solver::solve();
return 0;
}