【题解】
首先求出分出的最少区间数:n=ceil(B/D),ceil():向上取整
然后依据每一段的宽度w=B/n及弧长L/=n来求"深度"h即可,答案为:y=H-h
w,h可确定一条抛物线,其弧长L关于h单调递增,考虑二分h,验证弧长
设抛物线顶点为原点,由(w/2,d)在抛物线上可知其方程为:y=a*x^2,其中a=4*h/(w*w)
可导函数f(x)在区间[a,b]上的弧长:有公式(无法打出来),可以用微元法来推导,公式中的积分部分用自适应Simpson公式来求
【代码】
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
double w,h,_a;//_a:设 F(x)=_a*x^2
double F(double x)
{
return sqrt(1+4*_a*_a*x*x);
}
double simpson(double a,double b)//三点simpson法
{
double c=(a+b)/2;
return (b-a)/6*(F(a)+4*F(c)+F(b));
}
double asr(double a,double b,double eps,double A)//递归过程
{
double c=(a+b)/2,L=simpson(a,c),R=simpson(c,b);
if(fabs(L+R-A)<=15*eps) return L+R+(L+R-A)/15;
return asr(a,c,eps/2,L)+asr(c,b,eps/2,R);
}
int main()
{
double H,L,left,right;
int T,D,B,n,i;
scanf("%d",&T);
for(i=1;i<=T;i++)
{
scanf("%d%lf%d%lf",&D,&H,&B,&L);
n=(B+D-1)/D;//平均分成的段数
L/=(double)n;//每段绳索长
w=(double)B/(double)n;//每段宽度
left=0;
right=H;
while(right-left>1e-4)//二分桥的"深度"h==H-y
{
h=(left+right)/2;
_a=4*h/(w*w);
if(2*asr(0,w/2,1e-4,simpson(0,w/2))<=L) left=h;
else right=h;
}
if(i>1) printf("\n");
printf("Case %d:\n%.2lf\n",i,H-h);
}
return 0;
}