• bzoj1502 simpson求面积


    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1502

    题解:

    simpson积分求面积,s = (f(a)+f(b)+4*f(c))/6*Δx ,c=(a+b)/2。

    题中的树投影下来是一些圆和相邻圆的公切线组成的一个封闭图形,并且上下对称,所以可以只求上半部分。

    simpson求面积时,若f(x)代价很大,要尽量减少其的重复调用。其次尽量优化f(x)函数的计算。

    写完后还要自己出极限随机数据,将eps调到能接受的最大值。

      1 #include <cstdio>
      2 #include <cmath>
      3 #include <iostream>
      4 #define maxn 510
      5 #define eps 1e-6
      6 using namespace std;
      7 
      8 int sg( double x ) {
      9     return (x>-eps)-(x<eps);
     10 }
     11 struct Vector {
     12     double x, y;
     13     Vector(){}
     14     Vector( double x, double y ) : x(x), y(y) {}
     15     Vector operator+( Vector b ) { return Vector(x+b.x,y+b.y); }
     16     Vector operator-( Vector b ) { return Vector(x-b.x,y-b.y); }
     17     Vector operator*( double b ) { return Vector(x*b,y*b); }
     18     double len() {
     19         return sqrt( x*x+y*y );
     20     }
     21 };
     22 typedef Vector Point;
     23 
     24 struct Line {
     25     Point A, B;
     26     double k, b;
     27     double lf, rg;
     28     Line(){}
     29     Line( Point A, Point B ):A(A),B(B) {
     30         if( A.x>B.x ) swap(A,B);
     31         lf = A.x;
     32         rg = B.x;
     33         k = (B.y-A.y)/(B.x-A.x);
     34         b = A.y-A.x*k;
     35     }
     36     inline bool in( double x ) {
     37         return sg(x-lf)>=0 && sg(rg-x)>=0;
     38     }
     39     inline double f( double x ) { return k*x+b; }
     40     void out() {
     41         printf( "(%lf,%lf) (%lf,%lf) 
    ", A.x, A.y, B.x, B.y );
     42     }
     43 };
     44 struct Circle {
     45     Point C;
     46     double r;
     47     double lf, rg;
     48     Circle(){}
     49     void make() {
     50         lf = C.x-r;
     51         rg = C.x+r;
     52     }
     53     inline bool in( double x ) {
     54         return sg(x-lf)>=0 && sg(rg-x)>=0;
     55     }
     56     inline double f( double x ) {
     57         return sqrt( r*r-(C.x-x)*(C.x-x) );
     58     }
     59     void out() {
     60         printf( "(%lf,%lf) r=%lf
    ", C.x, C.y, r );
     61     }
     62 };
     63 
     64 int n; 
     65 double alpha;
     66 Line lines[maxn];
     67 Circle cirs[maxn];
     68 
     69 Line cir_tang( Circle & a, Circle & b ) {
     70     double ang = acos( (a.r-b.r)/(b.C.x-a.C.x) );
     71     Point A = a.C + Vector(cos(ang),sin(ang))*a.r;
     72     Point B = b.C + Vector(cos(ang),sin(ang))*b.r;
     73     return Line(A,B);
     74 }
     75 
     76 double F( double x ) {
     77     double y = -1.0;
     78     for( int i=0; i<=n; i++ ) {
     79         if( cirs[i].lf-eps<=x && x<=cirs[i].rg+eps ) 
     80             y = max( y, cirs[i].f(x) );
     81         if( i&& lines[i].lf-eps<=x && x<=lines[i].rg+eps ) 
     82             y = max( y, lines[i].f(x) );
     83     }
     84     return y;
     85 }
     86 inline double simpson( double a, double b, double fa, double fb, double fc ) {
     87     return (fa+4*fc+fb)*(b-a)/6;
     88 }
     89 double adapt( double a, double b, double c, double fa, double fb, double fc ) {
     90     double d = (a+c)/2, e = (c+b)/2;
     91     double fd = F(d), fe = F(e);
     92     double sa = simpson(a,c,fa,fc,fd);
     93     double sb = simpson(c,b,fc,fb,fe);
     94     double ss = simpson(a,b,fa,fb,fc);
     95     if( fabs(sa+sb-ss)<15*eps ) return sa+sb;
     96     return adapt(a,c,d,fa,fc,fd)+adapt(c,b,e,fc,fb,fe);
     97 }
     98 
     99 int main() {
    100     scanf( "%d%lf", &n, &alpha );
    101     double k = 1/tan(alpha);
    102     double hsum = 0.0, h;
    103     double lf=1e200, rg=-1e200;
    104     for( int i=0; i<=n; i++ ) {
    105         scanf( "%lf", &h );
    106         hsum += h;
    107         cirs[i].C.x = hsum*k;
    108         cirs[i].C.y = 0.0;
    109     }
    110     for( int i=0; i<n; i++ )  {
    111         scanf( "%lf", &cirs[i].r );
    112         cirs[i].make();
    113         lf = min( lf, cirs[i].lf );
    114         rg = max( rg, cirs[i].rg );
    115     }
    116     cirs[n].r = 0.0;
    117     rg = max( rg, cirs[n].C.x );
    118     for( int i=1; i<=n; i++ ) 
    119         lines[i] = cir_tang( cirs[i-1], cirs[i] );
    120     printf( "%.2lf
    ", adapt(lf,rg,(lf+rg)/2,F(lf),F(rg),F((lf+rg)/2) )*2 );
    121 }
    View Code
  • 相关阅读:
    在matlab中出现警告 Function call XX invokes inexact match
    VC2008调用matlab生成的dll和lib
    关于mwArray 的一些资料(一)
    关于C#中的3个timer类(申明是转贴的哦)
    C#教程 PDF
    我也做他个vote machine
    如何用UltraEdit编译C#源程序(再次申明这也是转贴的哦!)
    C#使用技巧调用DLL(还是转贴哦!)
    线程池
    Java web开发中如何自动生成文章html页面
  • 原文地址:https://www.cnblogs.com/idy002/p/4275443.html
Copyright © 2020-2023  润新知