BZOJ1502: [NOI2005]月下柠檬树

Simpson法相当好用啊!神奇的骗分算法!

 1 /**************************************************************

 2     Problem: 1502

 3     User: zhuohan123

 4     Language: C++

 5     Result: Accepted

 6     Time:228 ms

 7     Memory:1312 kb

 8 ****************************************************************/

 9  

10 #include <iostream>

11 #include <cstdio>

12 #include <cstring>

13 #include <cmath>

14 #include <algorithm>

15 using namespace std;

16 const double eps=1e-8,pi=3.141592653589793238;

17 int n;

18 struct point

19 {

20     double x,y;

21     point(){}

22     point(double X,double Y){x=X,y=Y;}

23 };

24 struct line

25 {

26     point s,e;

27     line(){}

28     line(point S,point E){s=S,e=E;}

29     double y(double x){return (e.y*s.x-e.x*s.y-e.y*x+s.y*x)/(s.x-e.x);}

30 }l[510];int lnum;

31 struct circle{double x,r;}c[510];

32 double h[510];

33 double f(double x)

34 {

35     double s=0;

36     for(int i=1;i<n;i++)

37     {

38         if(abs(x-c[i].x)+eps<c[i].r)s=max(s,sqrt(c[i].r*c[i].r-(x-c[i].x)*(x-c[i].x)));

39         if(l[i].s.x<x+eps&&l[i].e.x>x-eps)s=max(s,l[i].y(x));

40     }

41     return s*2;

42 }

43 const double dev=1e-6;

44 inline double simpson(double l,double r,double fl,double fm,double fr){return (fl+4*fm+fr)/6*(r-l);}

45 double integral(double l,double fl,double m,double fm,double r,double fr,double pre)

46 {

47     double lm=(l+m)/2,rm=(m+r)/2,flm=f(lm),frm=f(rm);

48     double intl=simpson(l,m,fl,flm,fm),intr=simpson(m,r,fm,frm,fr);

49     return abs(intl+intr-pre)<dev?intl+intr:integral(l,fl,lm,flm,m,fm,intl)+integral(m,fm,rm,frm,r,fr,intr);

50 }

51 int main(int argc, char *argv[])

52 {

53     double alp;scanf("%d%lf",&n,&alp);n++;

54     for(int i=1;i<=n;i++)scanf("%lf",&h[i]);

55     for(int i=1;i<n;i++)scanf("%lf",&c[i].r);c[n].r=0;

56     double s=1e10,e=-1e10;

57     for(int i=1;i<=n;i++)

58     {

59         h[i]+=h[i-1];

60         c[i].x=h[i]/tan(alp);

61         s=min(s,c[i].x-c[i].r);

62         e=max(e,c[i].x+c[i].r);

63     }

64     for(int i=1;i<n;i++)

65     {

66         double dx=c[i+1].x-c[i].x,dr=c[i].r-c[i+1].r;

67         if(abs(dx)<abs(dr)+eps)continue ;

68         l[++lnum]=line(point(c[i].x+c[i].r/dx*dr,sqrt(c[i].r*c[i].r-(c[i].r/dx*dr)*(c[i].r/dx*dr)))

69                       ,point(c[i+1].x+c[i+1].r/dx*dr,sqrt(c[i+1].r*c[i+1].r-(c[i+1].r/dx*dr)*(c[i+1].r/dx*dr))));

70     }

71     double m=(s+e)/2,fm=f(m);

72     printf("%.2lf\n",integral(s,0,m,fm,e,0,simpson(s,e,0,fm,0)));

73     return 0;

74 }

 

你可能感兴趣的:(ZOJ)