自适应Simpson积分求面积并。
平行光啊,它有个好,照下来那影子和原来平行于地面的物体是全等。于是我们就有了横向排布着的一些圆和一些线段,然后算就好了。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 550;
const int INF = 0x3f3f3f3f;
#define EPS 1e-6
struct Circle {
double x,R;
}C[maxn];
struct Line {
double k,b;
double L,R;
}line[maxn];int lines=0;
int cnt;
int n;double alpha,L,R;
double F(double x) {
double ret = 0;
for(int i = 1; i <= lines; i++) {
if( x >= line[i].L && x <= line[i].R )
ret = max( ret, line[i].k * x + line[i].b );
}
for(int i = 1; i <= n; i++ ) {
if( x >= C[i].x-C[i].R && x <= C[i].x + C[i].R ) {
ret = max( ret , sqrt ( C[i].R * C[i].R - (x-C[i].x)*(x-C[i].x) ) );
}
}
return ret;
}
double Simpson(double L,double R,double mid,double FL,double FR,double FM) {
double tFL = F( (L+mid)/2), tFR = F((mid+R)/2);
double ans = (R-L)*(FL+FR+4*FM)/6;
double Lans = (mid-L)*(FL+FM+4*tFL)/6;
double Rans = (R-mid)*(FM+FR+4*tFR)/6;
if (fabs(Lans+Rans-ans) < EPS ) return ans;
return Simpson(L,mid,(L+mid)/2,FL,FM,tFL) + Simpson(mid,R,(mid+R)/2,FM,FR,tFR);
}
int main() {
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d%lf",&n,&alpha);n++;
alpha = 1.0 / tan(alpha);
C[0].x=0;
for(int i = 1; i <= n; i++) {
double x;
scanf("%lf",&x);
C[i].x = C[i-1].x + x * alpha;
}
L=INF;R=-INF;
for(int i = 1; i <= n; i++) {
scanf("%lf",&C[i].R);
L = min(L, C[i].x - C[i].R);
R = max(R, C[i].x + C[i].R);
}
for(int i = 1; i < n; i++) {
if( C[i+1].x-C[i].x - fabs(C[i+1].R-C[i].R) < EPS ) continue;
lines++;
double sina = ( C[i].R - C[i+1].R) / ( C[i].x - C[i+1].x);
double cosa = sqrt(1.0 - sina*sina);
double tana = sina / cosa;
line[lines].L = C[i].x - C[i].R * sina;
line[lines].R = C[i+1].x - C[i+1].R * sina;
line[lines].k = tana;
line[lines].b = C[i].R * cosa - line[lines].L * tana;
}
printf("%.2lf\n",2*Simpson(L,R,(L+R)/2.0,0,0,F((L+R)/2.0)));
}