【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;
}
posted @ 2018-05-23 17:25  sigongzi  阅读(180)  评论(0编辑  收藏  举报