【题目链接】
【思路要点】
- 将X轴根据整点分成若干段,对每一段横坐标用自适应Simpson积分计算面积。
- 时间复杂度\(O(Cnt*NLogN)\),其中\(Cnt\)为自适应Simpson积分的迭代次数。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 1005; const int INF = 1e9; const double eps = 1e-8; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } struct circle {int x, y, r; }; struct info {double x; bool type; }; int n, m; bool del[MAXN]; circle a[MAXN], b[MAXN]; bool cmp(info a, info b) {return a.x < b.x; } double f(double pos) { double ans = 0; int tot = 0; info tmp[MAXN * 2]; for (int i = 1; i <= n; i++) { double d = a[i].r * a[i].r - (a[i].x - pos) * (a[i].x - pos); if (fabs(d) <= eps) continue; d = sqrt(d); tmp[++tot] = (info) {a[i].y - d, true}; tmp[++tot] = (info) {a[i].y + d, false}; } sort(tmp + 1, tmp + tot + 1, cmp); int cnt = 0; double last = 0; for (int i = 1; i <= tot; i++) { if (tmp[i].type) { if (++cnt == 1) last = tmp[i].x; } else if (--cnt == 0) ans += tmp[i].x - last; } return ans; } double inter(double l, double r) { double mid = (l + r) / 2; return (f(l) + 4 * f(mid) + f(r)) / 6 * (r - l); } double calc(double l, double r, double now) { double mid = (l + r) / 2; double nowl = inter(l, mid); double nowr = inter(mid, r); if (fabs(now - nowl - nowr) <= eps) return now; else return calc(l, mid, nowl) + calc(mid, r, nowr); } int main() { read(n); for (int i = 1; i <= n; i++) read(a[i].x), read(a[i].y), read(a[i].r); int Min = INF, Max = -INF; for (int i = 1; i <= n; i++) { chkmin(Min, a[i].x - a[i].r); chkmax(Max, a[i].x + a[i].r); if (del[i]) continue; for (int j = 1; j <= n; j++) if (j != i && !del[j] && a[j].r >= a[i].r && (a[j].r - a[i].r) * (a[j].r - a[i].r) >= (a[i].x - a[j].x) * (a[i].x - a[j].x) + (a[i].y - a[j].y) * (a[i].y - a[j].y)) { del[i] = true; break; } } m = 0; for (int i = 1; i <= n; i++) if (!del[i]) b[++m] = a[i]; double ans = 0; for (int i = Min; i < Max; i++) { n = 0; for (int j = 1; j <= m; j++) if (i >= b[j].x - b[j].r && i < b[j].x + b[j].r) a[++n] = b[j]; ans += calc(i, i + 1, inter(i, i + 1)); } printf("%.3lf\n", ans); return 0; }