题意:桥上等距离放着若干的塔,高为H,相邻两座塔之间的距离不得超过D,塔之间有绳
索,为抛物线,桥长度为B,绳索长度为L,问你建造最少塔时绳索最下端距离地面的高度。
思路:注意到相同的宽度下,抛物线高度和长度成正比,所以我们二分高度,求长度,抛物线的积分公式为√(1+(f’(x))^2),利用辛普森公式就能很轻松的求出~
第一次用辛普森,好激动~
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
using namespace std;
const double eps = 1e-8;
double D, H, B, L;
double a;
int cas = 0;
double F(double x){
return sqrt(1 + 4 * a * a * x * x);
}
double simpson(double a, double b){
double c = a + (b - a) / 2;
return (F(a) + 4 * F(c) + F(b)) * (b - a) / 6;
}
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) <= eps) return L + R + (L + R - A) / 15;
return asr(a, c, eps / 2, L) + asr(c, b, eps / 2, R);
}
double asr(double a, double b, double eps){
return asr(a, b, eps, simpson(a, b));
}
void solve(){
scanf("%lf%lf%lf%lf", &D, &H, &B, &L);
int n = ceil(B / D);
double D1 = B / n;
double L1 = L / n;
double l = 0, r = H;
while(l + eps < r){
double mid = (l + r) / 2;
a = 4 * mid / (D1 * D1);
if(2 * asr(0, D1 / 2, 1e-8) > L1) r = mid;
else l = mid;
}
if(cas++) printf("\n");
printf("Case %d:\n", cas);
printf("%.2lf\n", H - l);
}
int main()
{
int T;
scanf("%d", &T);
while(T--) solve();
return 0;
}