您的位置:首页 > 其它

UVALive - 3485 Bridge 二分+数学+自适应辛普森求积分

2017-10-14 12:24 441 查看
题意:

给定抛物线长度L和开口大小,算出抛物线的高度(离地高度).

思路:

可导函数f(x)在区间[a,b]上的弧长为:

∫ba1+[f′(x)]2−−−−−−−−−√dx

我们可以给该抛物线列一个方程,当然是越简单越容易求解.

这道题目可以发现当h变化时,抛物线的弧长也在变化,且随着h单调递增,我们可以根据这个性质二分h然后带入验证进而求出解.

但是这个积分不是很好求,这里我们可以根据自适应辛普森求积分.

#include<bits/stdc++.h>

using namespace std;
const int maxn = 1e5+5;
const double eps = 1e-5;
double a;
double f(double x)
{
return sqrt(1+4*a*a*x*x);
}
//三点simpson法,这里f要求是一个全局函数.
/*三点simpson积分公式
(b-a)/6 *{f(a)+4*f((a+b)/2)+f(b)}
*/
double simpson(double a,double b)
{
double c = a + (b-a)/2;
return (f(a)+4*f(c)+f(b))*(b-a)/6;
}
//自适应simpson公式(递归过程)
//已知整个区间[a,b]上的三点simpson值A
//当|S(a,c)+S(c,b)-S(a,b)|< 15eps 直接返回结果
double asr(double a,double b,double eps,double A)
{
double c = a + (b-a)/2;
double L = simpson(a,c),R = simpson(c,b);
if(fabs(L+R-A) <= 15*eps) return L+R+(L+R-A)/15.0;
return asr(a,c,eps/2,L) + asr(c,b,eps/2,R);
}

//自适应辛普森求积分(主过程).
//[a,b]分别为积分上下界,eps为精度。
double asr(double a,double b,double eps)
{
return asr(a,b,eps,simpson(a,b));
}
//求积分
double check(double w,double h)
{
a = 4.0*h/(w*w);
return 2*asr(0,w/2,eps);
}
int main()
{
int D,H,B,L;
int ca = 1,_;
cin>>_;
bool flag = 0;
while(_--)
{
scanf("%d %d %d %d",&D,&H,&B,&L);
int n = (B + D - 1)/D;
double D1 = B*1.0/n;
double L1 = L*1.0/n;
double l = 0,r = H,mid;
while(r - l > eps)
{
mid = (l + r) / 2;
if(check(D1,mid) < L1) l = mid;
else r = mid;
}
if(flag)
puts("");
printf("Case %d:\n%.2f\n",ca++,H-l);
flag = 1;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: