POJ 1905 Expanding Rods(二分法,简单几何知识)

来源:互联网 发布:linux设置dns命令 编辑:程序博客网 时间:2024/05/21 12:42

Description

When a thin rod of length L is heated n degrees, it expands to a new length L'=(1+n*C)*L, where C is the coefficient of heat expansion. 
When a thin rod is mounted on two solid walls and then heated, it expands and takes the shape of a circular segment, the original rod being the chord of the segment. 

Your task is to compute the distance by which the center of the rod is displaced. 

Input

The input contains multiple lines. Each line of input contains three non-negative numbers: the initial lenth of the rod in millimeters, the temperature change in degrees and the coefficient of heat expansion of the material. Input data guarantee that no rod expands by more than one half of its original length. The last line of input contains three negative numbers and it should not be processed.

Output

For each line of input, output one line with the displacement of the center of the rod in millimeters with 3 digits of precision. 

Sample Input

1000 100 0.000115000 10 0.0000610 0 0.001-1 -1 -1

Sample Output

61.329225.0200.000


题目大意:

        两面墙的间距为L,中间恰好夹了一根长度为L的金属棒,金属棒有一个热膨胀系数C,受热后长度会发生改变,加热n度后长度为L'=(1+n*C)*L,因为两面墙是固定的,金属棒变长后会发生弯曲,给定n,C,L,求膨胀后金属棒中点上升的高度h。

解题思路:

        设所求高度为h,圆弧的半径为R,金属棒原长L,加热后长度(弧长)L',则有R^2=(L/2)^2+(R-h)^2,整理后得到R=(L^2+4h^2)/(8h),弧长L‘=2*R*arcsin(L/2R),通过二分枚举h求得R,通过R求得L’,然后与热膨胀公式求得的准确L'比较,决定向左二分还是向右二分,详见代码:


#include <iostream>#include <fstream>#include <cstdio>#include <cmath>#include <map>#include <set>#include <bitset>#include <ctime>#include <cstring>#include <algorithm>#include <stack>#include <queue>#include <vector>#include <list>#define STD_REOPEN() freopen("../in.in","r",stdin)#define STREAM_REOPEN fstream cin("../in.in")#define INF 0x3f3f3f3f#define _INF 63#define eps 1e-8#define MAX_V 100010#define MAX_P 110#define MAX_E 10010#define MAX 32000#define MOD_P 3221225473#define MOD 9901using namespace std;const double PI=acos(-1.0);int dcmp(double x){return fabs(x)<eps?0:(x<0?-1:1);}int main(){//STD_REOPEN();double L0,n,C;while(~scanf("%lf %lf %lf",&L0,&n,&C)){if(L0<0&&n<0&&C<0)break;double L=(1+n*C)*L0;double l=0,r=L0;double mid;while(dcmp(r-l)>0){mid=(l+r)/2;double R=(L0*L0+4*mid*mid)/(8*mid);double tmp=R*2*asin(L0/(2*R));if(dcmp(tmp-L)>0)//求得的弧长比实际大,说明枚举的h过大,则向左二分r=mid;else//否则向右二分l=mid;}printf("%.3f\n",mid);}    return 0;}


0 0