zoukankan      html  css  js  c++  java
  • UVa1356

    1356 Bridge
    A suspension bridge suspends the roadway from huge main cables, which extend from one end of the
    bridge to the other. These cables rest on top of high towers and are secured at each end by anchorages.
    The towers enable the main cables to be draped over long distances.
    Suppose that the maximum distance between two neighboring towers is D, and that the distance
    from the top of a tower to the roadway is H. Also suppose that the shape of a cable between any two
    neighboring towers is the same symmetric parabola (as shown in the gure). Now given B, the length
    of the bridge and L, the total length of the cables, you are asked to calculate the distance between the
    roadway and the lowest point of the cable, with minimum number of towers built (Assume that there
    are always two towers built at the two ends of a bridge).
    Input
    Standard input will contain multiple test cases. The rst line of the input is a single integer T (1 
    T  10) which is the number of test cases. T test cases follow, each preceded by a single blank line.
    For each test case, 4 positive integers are given on a single line.
    D - the maximum distance between two neighboring towers;
    H - the distance from the top of a tower to the roadway;
    B - the length of the bridge; and
    L - the total length of the cables.
    It is guaranteed that B  L. The cable will always be above the roadway.
    Output
    Results should be directed to standard output. Start each case with `Case #:' on a single line, where
    # is the case number starting from 1. Two consecutive cases should be separated by a single blank
    line. No blank line should be produced after the last test case.
    For each test case, print the distance between the roadway and the lowest point of the cable, as is
    described in the problem. The value must be accurate up to two decimal places.
    Universidad de Valladolid OJ: 1356 { Bridge 2/2
    Sample Input
    2
    20 101 400 4042
    1 2 3 4
    Sample Output
    Case 1:
    1.00
    Case 2:
    1.60

    题意:

           修建一座大桥。桥上等距地摆放着若干个塔,塔高为H,宽度忽略,相邻两座塔之间的距离不能超过D。塔之间的绳索形成全等的对称抛物线。桥的总长为B,绳索总长为L,求建造最少的塔时绳索的最下端距离地的高度y。

    分析:

           这道题可以使用数学知识进行求解,设塔的数量最少时,间隔数为n,则n=ceil(B/D),每个间隔的宽度是D1=B/n,每段绳索的长度是L1=L/n。由数学知识可以根据L1以及D1求解绳索最低端离地高度。实际上y可以通过解方程求得。设宽度为w,高度为h,顶点在原点的抛物线长度是p(w,h)。于是我们需要求解一个关于h的方程p(D1,h) = L1。注意到p(D1,h)是一个关于h的增函数,所以我们可以使用二分求解。而p(w,h)只能根据抛物线的方程加上其对称性由定积分求得。

     1 #include <cstdio>
     2 #include <cmath>
     3 #define eps 1e-5
     4 // sqrt(a^2 + x^2)的原函数
     5 double F(double a,double x){
     6     double a2 = a * a,x2 = x * x;
     7     return (x * sqrt(a2 + x2) + a2 * log(fabs(x + sqrt(a2 + x2)))) / 2;
     8 }
     9 // 宽度为w,高度为h的抛物线长度,也就是p(w,h)
    10 double parabola_arc_length(double w,double h){
    11     double a = 4.0 * h / (w * w);
    12     double b = 1.0 / (2 * a);
    13     return (F(b,w / 2) - F(b,0)) * 4 * a; // 利用对称性
    14 }
    15 int main(){
    16     int T; scanf("%d",&T);
    17     for(int kase = 1 ; kase <= T ; kase++){
    18         int D,H,B,L; scanf("%d%d%d%d",&D,&H,&B,&L);
    19         int n = (B + D - 1) / D; // 间隔数
    20         double D1 = 1.0 * B / n;
    21         double L1 = 1.0 * L / n;
    22         double x = 0,y = H;
    23         while(y - x > eps){
    24             double m = x + (y - x) / 2;
    25             if(parabola_arc_length(D1,m) < L1) x = m; else y = m;
    26         }
    27         if(kase > 1) printf("
    ");
    28         printf("Case %d:
    %.2lf
    ",kase,H - x);
    29     }
    30     return 0;
    31 }
    View Code

    但是有的时候函数的积分不易求得或者函数的原函数不能用初等函数进行表示,这时候我们可以利用辛普森公式来近似计算曲线与坐标轴围成的面积去估计积分值。

     1 #include <cstdio>
     2 #include <cmath>
     3 const double eps = 1e-5;
     4 // 被积函数F
     5 double a;
     6 double F(double x){
     7     return sqrt(1 + 4 * a * a * x * x);
     8 }
     9 // 三点Simpson法。这里要求F是一个全局函数,F也就是被积函数
    10 double simpson(double a,double b){
    11     double c = a + (b - a) / 2;
    12     return (F(a) + 4 * F(c) + F(b)) * (b - a) / 6;
    13 }
    14 // 自适应Simpson公式(递归过程)。已知整个区间[a,b]上的三点Simpson值A
    15 double asr(double a,double b,double eps,double A){
    16     double c = a + (b - a) / 2;
    17     double L = simpson(a,c),R = simpson(c,b);
    18     if(fabs(L + R - A) <= 15 * eps) return L + R + (L + R - A) / 15.0;
    19     return asr(a,c,eps / 2,L) + asr(c,b,eps / 2,R);
    20 }
    21 // 自适应Simpson公式(主过程)
    22 double asr(double a,double b,double eps){
    23     return asr(a,b,eps,simpson(a,b));
    24 }
    25 // 用自适应Simpson公式计算宽为w
    26 double parabola_arc_length(double w,double h){
    27     a = 4.0 * h / (w * w); // 修改全局变量a,从而影响F的行为
    28     return asr(0,w / 2,eps) * 2;
    29 }
    30 int main(){
    31     int T; scanf("%d",&T);
    32     for(int kase = 1 ; kase <= T ; kase++){
    33         int D,H,B,L; scanf("%d%d%d%d",&D,&H,&B,&L);
    34         int n = (B + D - 1) / D; // 间隔数
    35         double D1 = 1.0 * B / n;
    36         double L1 = 1.0 * L / n;
    37         double x = 0,y = H;
    38         while(y - x > eps){
    39             double m = x + (y - x) / 2;
    40             if(parabola_arc_length(D1,m) < L1) x = m; else y = m;
    41         }
    42         if(kase > 1) printf("
    ");
    43         printf("Case %d:
    %.2lf
    ",kase,H - x);
    44     }
    45     return 0;
    46 }
    View Code
  • 相关阅读:
    WPF 模拟UI 键盘录入
    rabbitmq使用dead letter机制来进行retry
    工厂设计模式
    python 内置速度最快算法(堆排)
    简单工厂设计模式
    杂类
    MorkDown 常用语法总结
    使用python列表推导式进行99乘法表
    linux 命令free -m 命令结果分析
    理解记忆三种常见字符编码:ASCII, Unicode,UTF-8
  • 原文地址:https://www.cnblogs.com/cyb123456/p/5833819.html
Copyright © 2011-2022 走看看