UVA 1356/ ZOJ 2614 Bridge 弧长积分+二分

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//对积分sqrt(a^2+x^2)的求解
double fun(double a,double x)
{
    double aa=a*a,xx=x*x;
    return (x*sqrt(aa+xx)+aa*log(fabs(x+sqrt(aa+xx))))/2;
}
//求宽w,高h的抛物线弧长
double parabola(double w,double h)
{
    double a=4.0*h/(w*w);
    double b=1.0/(2*a);
    return (fun(b,w/2)-fun(b,0))*4*a;
}
int main()
{
    int T,tt=0;
    scanf("%d",&T);
    while(T--)
    {
        int d,h,b,l;
        scanf("%d%d%d%d",&d,&h,&b,&l);
        int n=(b+d-1)/d;//间隔数
        double d1=(double)b/n;
        double l1=(double)l/n;
        double x=0,y=h;
        //弧长随h单调递增,所以用二分法求得h
        while(y-x>1e-5)
        {
            double m=(x+y)/2;
            if(parabola(d1,m)<l1)x=m;
            else y=m;
        }
        if(tt!=0)
            printf("\n");
        printf("Case %d:\n%.2lf\n",++tt,h-x);
    }
    return 0;
}
/*
    纯粹的数学积分题,高数不行啊,寒一个。。。。
    
    建立抛物线公式f(x)=a*x^2,其中a=4*h/(w*w);
    有积分中的弧长公式2∫(0,w/2)√(1+(f'(x))^2)dx=2∫(0,w/2)√(1+4*a^2*x^2)^2)dx
=4a∫(0,w/2)√((1/(2*a))^2+x^2)dx
    
    再由积分表公式∫√(a^2+x^2)dx=1/2*x*sqrt(a^2+x^2)+1/2*a*a*log(fabs(x+sqrt(a*a+x*x)))+C求得弧长
    
    最后二分高度,求得答案
*/

你可能感兴趣的:(二分,弧长积分)