BZOJ 1502 月下柠檬树 simpson积分

题解:
投在地上的影子是很多圆和两圆公切线组成的梯形的面积并。

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 }

 

 

posted @ 2013-03-02 19:36  proverbs  阅读(872)  评论(0编辑  收藏  举报