【BZOJ】2178: 圆的面积并
题解
道理我都懂,可这精度卡得也太过分了吧
1e-10 AC 1e-12 WA,maya
就是把每个横坐标上圆覆盖的纵坐标长度求出来,对这个函数做一次simpson就行
代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
//#define ivorysi
#define pb push_back
#define MAXN 1005
#define eps 1e-10
#define space putchar(' ')
#define enter putchar('\n')
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long int64;
typedef double db;
int N;
bool dcmp(db a,db b) {
return fabs(a - b) <= eps;
}
struct cir {
db x,y,r;
friend bool operator < (const cir &a,const cir &b) {
return (a.x - a.r) < (b.x - b.r);
}
}C[MAXN];
pair<db,db> L[MAXN];
inline db o (db x) {return x * x;}
db Calc(db x) {
int tot = 0;
for(int i = 1 ; i <= N ; ++i) {
if(x < C[i].x - C[i].r - eps || x > C[i].x + C[i].r + eps) continue;
db t = sqrt(o(C[i].r) - o(x - C[i].x));
L[++tot] = mp(C[i].y - t,C[i].y + t);
}
sort(L + 1,L + tot + 1);
if(!tot) return 0;
db res = 0,s = L[1].fi,mx = L[1].se;
for(int i = 2 ; i <= tot ; ++i) {
if(L[i].fi > mx) {
res += mx - s;
s = L[i].fi;
}
mx = max(mx,L[i].se);
}
res += mx - s;
return res;
}
db Simpson(db L,db R,db fl,db fmid,db fr) {
db mid = (L + R) / 2;
db Slr = (R - L) * (fl + 4 * fmid + fr) / 6;
db p = Calc((L + mid) / 2),q = Calc((mid + R) / 2);
db Sl = (mid - L) * (fl + 4 * p + fmid) / 6;
db Sr = (R - mid) * (fmid + 4 * q + fr) / 6;
if(dcmp(Slr,Sl + Sr)) return Sl + Sr;
else return Simpson(L,mid,fl,p,fmid) + Simpson(mid,R,fmid,q,fr);
}
void Solve() {
scanf("%d",&N);
for(int i = 1 ; i <= N ; ++i) scanf("%lf%lf%lf",&C[i].x,&C[i].y,&C[i].r);
db res = Simpson(-2001,2001,Calc(-2001),Calc(0),Calc(2001));
printf("%.3lf\n",res);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}