zoukankan      html  css  js  c++  java
  • openjudge-膨胀的木棍

    http://noi.openjudge.cn/ch0111/09/

    总时间限制: 1000ms  内存限制: 65536kB
    描述

    当长度为L的一根细木棍的温度升高n度,它会膨胀到新的长度L'=(1+n*C)*L,其中C是热膨胀系数。

    当一根细木棍被嵌在两堵墙之间被加热,它将膨胀形成弓形的弧,而这个弓形的弦恰好是未加热前木棍的原始位置。

    你的任务是计算木棍中心的偏移距离。

     输入

    三个非负实数:木棍初始长度(单位:毫米),温度变化(单位:度),以及材料的热膨胀系数。
    保证木棍不会膨胀到超过原始长度的1.5倍。

    输出

    木棍中心的偏移距离(单位:毫米),保留到小数点后第三位。

    样例输入

    1000 100 0.0001

    样例输出

    61.329

     参考:

    http://blog.csdn.net/jeremygjy/article/details/49686943

    http://blog.csdn.net/txl199106/article/details/49332261

     1 #include<stdio.h>
     2 #include<math.h>
     3 #define PI (acos(-1))
     4 #define eps (1e-14)
     5 int main(int argc, char *argv[])
     6 {
     7     double L,n,C,L1;
     8     
     9     double minCentralAngle,maxCentralAngle,CentralAngle;
    10     double radius,L2;
    11     double ans;
    12     
    13     scanf("%lf%lf%lf",&L,&n,&C);
    14     
    15     if(n*C*L<=eps)   //假如膨胀量太小就不用计算了,直接认为结果就是0. 
    16     {
    17         printf("0.000
    ");
    18         return 0;
    19     }
    20     
    21     L1=(1+n*C)*L;
    22     
    23     //下面对圆心角进行二分枚举
    24     //(膨胀量不超过原来的1.5倍,
    25     //分析圆的半周长PI*R与直径2*R的关系可知圆心角范围0~2*PI而且不可能取2*PI) 
    26     minCentralAngle=0;//圆心角的极小值 
    27     maxCentralAngle=PI;//圆心角的极大值 
    28     while(minCentralAngle<maxCentralAngle-eps)
    29     {
    30         CentralAngle=(minCentralAngle+maxCentralAngle)/2;
    31         radius=L/2/sin(CentralAngle/2);
    32         L2=CentralAngle*radius;
    33         if(L2>=L1)//当弦长固定时,圆心角越大 ,弧长就越大 
    34             maxCentralAngle=CentralAngle;
    35         else if(L2<L1)
    36             minCentralAngle=CentralAngle;
    37     }
    38     radius=L/2/sin(minCentralAngle/2);
    39     ans=radius-L/2/tan(minCentralAngle/2);
    40     printf("%.3lf
    ",ans);
    41     return 0;
    42 }

    一定要注意:我们需要二分的内容是当前角度,那么角度的范围可以很容易发现,因为木棍长度不超过1.5倍那么就定角度为0-π因为如果圆心角过小会发现半径十分的大根本存不下,其实这种情况的时候木棍长度的变化也是十分的小的那么 

    if(n * c * L <= eps) 
    判断一下如果满足那么直接就输出0.000, 

    另外要注意:当弦长固定时,圆心角越大 ,弧长就越大 。

    网友JeremyGJY的代码和分析很好,摘抄一下:

    JeremyGJY的代码:

     1 #include <cstdio>
     2 #include <cmath>
     3 #include <algorithm>
     4 using namespace std;
     5 const double PI = asin(1.0);
     6 const double eps = 1e-14;
     7 int main(){
     8     double Len1, Len2, Temp, ks;
     9     while(scanf("%lf%lf%lf", &Len1, &Temp, &ks) != EOF){
    10         Len2 = (1.0 + Temp * ks) * Len1;
    11         double l=0, r=PI;
    12         if(Temp * ks * Len1 <= eps){
    13             printf("%.3lf
    ", 0.0);
    14             continue;
    15         }
    16         while(l < r - eps){
    17             double mid = (l + r)/2.0;
    18             if(Len1/sin(mid)*PI*(mid/PI) >= Len2)
    19                 r = mid;
    20             else l = mid;
    21         }
    22         printf("%.3lf
    ", Len1/2/sin(l)-Len1/2/sin(l)*cos(l));
    23     }
    24 
    25     return 0;
    26 }
    View Code

    csdn网友Tank_long的分析更精彩,只不过下面这个图的公式似乎有点乱。

    公式大概如下:

    首先要注意θ角是圆心角的一半。然后根据数学公式有:

    sinθ=2sin(θ/2)cos(θ/2)

    1-cosθ=2sin(θ/2)2

    然后还要注意根据直角三角形正弦的定义有:L=2*R*sinθ

    根据弧长公式有LL=2*R*θ

    所以h=R-R*cosθ=R*(1-cosθ)=L/(2*sinθ)*(1-cosθ)=L/(2*sinθ)*(2sin(θ/2)2)=L/( 2*  ( 2*sin(θ/2)*cos(θ/2)  )    )*(2sin(θ/2)2 )

    最后h=L/2*tan(θ/2)

    注意到θ是圆心角的一半,所以θ得区间是0~PI,根据正切函数图形性质可以知道当L固定时,h跟θ是成正比关系的。

    Tank_long的代码:(不得不佩服起数学功底啊……)

     1 #include<stdio.h>  
     2 #include<stdlib.h>  
     3 #include<math.h>  
     4 int main()  
     5 {  
     6     double l, ll, rig, lef, mid, n, c;  
     7     scanf("%lf%lf%lf", &l, &n, &c);  
     8   
     9     if(l<1e-14)  
    10     {  
    11         printf("0.000
    ");  
    12         return 0;  
    13     }  
    14     ll=l*(1+n*c);  
    15     lef=0.0;          //角的极小值  
    16     rig=asin(1.0);    //角的极大值  
    17     //由于三角函数转换,得到 h= (l/2)*tan(@/2) , 所以h只与角@有关,使用二分逼近法去求解最接近的@即可  
    18     //注意,二分验证是让 ll与角@ 计算得到的 木棍原始长度l`=ll*sin@/@ 与 l 进行比较,且l`与@成反比例关系  
    19     while(rig-lef>1e-14)   //在极大值与极小值之间进行二分,这个地方精度控制太低就过不了了。精度要求很高。  
    20     {  
    21         mid=(rig+lef)/2;  
    22         if(ll*sin(mid)/mid<=l)  
    23             rig=mid;  
    24         else  
    25             lef=mid;  
    26     }  
    27     printf("%.3lf
    ", l/2*tan(lef/2));  
    28     return 0;  
    29 }  
    View Code

    三角函数公式补充:

    二倍角公式

  • 相关阅读:
    优雅高效的MyBatis-Plus工具快速入门使用
    mybatis中#{}和${}的区别
    异常处理com.sun.image.codec.jpeg.JPEGImageEncoder
    图片压缩之-JPEGCodec失效替换方案
    Bugly实现app全量更新
    MyBatis下MySqL用户口令不能为空
    java.lang.OutOfMemoryError: PermGen space及其解决方法
    Hibernate or 的用法
    如何理解<base href="<%=basePath%>"
    小程序 wx.request ajax示例
  • 原文地址:https://www.cnblogs.com/huashanqingzhu/p/5662002.html
Copyright © 2011-2022 走看看