二分查找---膨胀的木棍

问题描述:
当长度为L的一根细木棍的温度升高n度,它会膨胀到新的长度L'=(1+n*C)*L,其中C是热膨胀系数。
当一根细木棍被嵌在两堵墙之间被加热,它将膨胀形成弓形的弧,而这个弓形的弦恰好是未加热前木棍的原始位置。
你的任务是计算木棍中心的偏移距离。

输入
三个非负实数:木棍初始长度(单位:毫米),温度变化(单位:度),以及材料的热膨胀系数。
保证木棍不会膨胀到超过原始长度的1.5倍。
输出
木棍中心的偏移距离(单位:毫米),保留到小数点后第三位。
样例输入
1000 100 0.0001
样例输出
61.329
问题分析:
由数学内容可知弧长和弦长有关,f(L) = 2rarcsin(L/2r) f(L)表示弦长,L表示弧长。我们可以通过枚举r,寻找能满足上述关系的r,我们知道r的下限是L/2,但是如何确定r的上限。arcsin(L/2r)随r的增大而减小,2r却在增大,所以整个函数的增减性不容易判断。故r的上限无法确定,也就没法办用二分查找。
此时,我们把关注点转向夹角,假设圆心角的度数为a,则有
2sin(a/2)/L*a = f(L),显然当a处于[0,pi]时,左侧函数递增,即左侧函数的函数值随a的增大而增大,那么他必然会和f(L)产生交汇点。这时就可以用折半查找来确定a的解,而a的上下限就是[0,pi]。

过程分析:
2sin(a/2)/L*a = f(L) (1)
这个题最大的亮点是不断的尝试a,让等式(1)的两边不断接近,求得最终a的取值,而不是想尽办法数学公式把a表示出来,然后代入求解。
参考答案:
#include<math.h>
#include<stdio.h>
#include<iostream>
using namespace std;
int main()
{
double L,La,n,C;
cin>>L>>n>>C;
La = (1+n*C)*L;
double l = 0, r = acos(-1),d,temp;
while(r-l>1 e-12 )#必须是这个精度,否则提交不了
{
//cout<<" ha "<<endl;
d = (r+l)/2;
temp = d*L/2/sin(d/2);
if(temp>=La)
r = d- 1e-12 ;
else
l = d+1 e-12 ;
//cout<<temp-La<<endl;

}
printf("%.3f",L/2/sin(d/2)*(1-cos(d/2)));
}























猜你喜欢

转载自blog.csdn.net/cleanarea/article/details/78762015