题解:
投在地上的影子是很多圆和两圆公切线组成的梯形的面积并。
PS:圆只要和地面平行,无论光从哪个角度照射,投影都是圆
其实应该一开始应先分成若干份做simpson的。。
View Code
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <cmath> 7 8 #define N 520 9 #define EPS 1e-6 10 11 using namespace std; 12 13 int n; 14 double a[N],b[N],af,h,lt,rt; 15 16 struct C 17 { 18 double x,y,p,q; 19 }c[N]; 20 21 inline int dc(double x) 22 { 23 if(x>EPS) return 1; 24 else if(x<-EPS) return -1; 25 return 0; 26 } 27 28 inline void read() 29 { 30 scanf("%d%lf",&n,&af); 31 af=1/tan(af); 32 for(int i=1;i<=n+1;i++) 33 { 34 scanf("%lf",&a[i]); 35 h+=a[i]; a[i]=h*af; 36 } 37 lt=a[1];rt=a[n+1]; 38 for(int i=1;i<=n;i++) 39 { 40 scanf("%lf",&b[i]); 41 lt=min(lt,a[i]-b[i]); 42 rt=max(rt,a[i]+b[i]); 43 } 44 } 45 46 inline void calc() 47 { 48 for(int i=1;i<=n;i++) 49 if(a[i+1]-a[i]>fabs(b[i+1]-b[i])) 50 { 51 c[i].x=a[i]+b[i]*(b[i]-b[i+1])/(a[i+1]-a[i]); 52 c[i].y=sqrt(b[i]*b[i]-(c[i].x-a[i])*(c[i].x-a[i])); 53 c[i].p=a[i+1]+b[i+1]*(b[i]-b[i+1])/(a[i+1]-a[i]); 54 c[i].q=sqrt(b[i+1]*b[i+1]-(c[i].p-a[i+1])*(c[i].p-a[i+1])); 55 } 56 } 57 58 inline double f(double p) 59 { 60 double res=0; 61 for(int i=1;i<=n;i++) 62 { 63 if(fabs(a[i]-p)<b[i]) res=max(res,sqrt(b[i]*b[i]-(a[i]-p)*(a[i]-p))); 64 if(p>c[i].x&&p<c[i].p) res=max(res,c[i].y-(p-c[i].x)*(c[i].y-c[i].q)/(c[i].p-c[i].x)); 65 } 66 return res; 67 } 68 69 inline double simpson(double l,double r,double fl,double fmid,double fr) 70 { 71 return (fl+fr+4*fmid)*(r-l)/6; 72 } 73 74 inline double rsimpson(double l,double r,double fl,double fmid,double fr) 75 { 76 double p,q,mid,x,y,z; 77 mid=(l+r)/2; 78 p=f((l+mid)/2); q=f((mid+r)/2); 79 x=simpson(l,r,fl,fmid,fr); y=simpson(l,mid,fl,p,fmid); z=simpson(mid,r,fmid,q,fr); 80 if(dc(fabs(x-y-z))==0) return y+z; 81 else return rsimpson(l,mid,fl,p,fmid)+rsimpson(mid,r,fmid,q,fr); 82 } 83 84 inline void go() 85 { 86 calc(); 87 printf("%.2lf\n",2*rsimpson(lt,rt,0,f(lt+rt)/2,0)); 88 } 89 90 int main() 91 { 92 read(),go(); 93 return 0; 94 }