POJ 1905 - Expanding Rods 【二分/三分】

来源:互联网 发布:软件著作权侵权认定 编辑:程序博客网 时间:2024/06/06 02:18

题目链接:http://poj.org/problem?id=1905

题意:

一根两端固定在两面墙上的杆 受热弯曲后变弯曲

求前后两个状态的杆的中点位置的距离

思路:如图所示,已知s,a 求x。设角度为rad,半径为r, 显然,我们有r = s/ rad = a/sin(rad);即a*rad-s*sin(rad)=0或者rad/sin(rad) = s/a。下面我们就根据这两个式子进行二分或三分。

法一:令函数f(rad) = rad/sin(rad) ,求导找单调性,f'(rad) = (sin(rad)-rad*cos(rad))/sin^2(rad) = cos(rad)/sin^2(rad)*(tan(rad)-rad),rad∈(0,π),故tan(rad)-rad>0;所以函数f(rad) 单调递增。接下来就对函数直接二分吧~

法二:令函数f(rad) = a*rad-s*sin(rad),目标是求函数的零点,当时我还没有去求导,直接就拿三分上,其实求下 导也是很容易的。下面讲讲我的思路吧。rad∈(0,π)不变,我在没有求导的情况下,也就是说在我还不知道函数的单调性的时候,但是在定义域范围内我知道单调区间最多就是两个,那么这个时候我就直接三分搜索答案了~

最后提醒大家一下,提交的时候注意不要用G++来提交printf("lf"),否则会WA,而C++可以AC,如果要用G++提交,大家不妨用cout<<fixed<<setprecision().....


/** *作者:__Xiong *日期:2015/7/24 */ //法一:二分#include <cmath>#include <cstdio>#include <string>#include <cstring>#include <iomanip>#include <iostream>#include <algorithm>using namespace std;const double eps = 1e-10;const double PI = 3.1415926535897932384626433832795;double N,C,L;int main(){    //freopen("input.in","r",stdin);    while(scanf("%lf%lf%lf",&L,&N,&C)&&N>=0&&C>=0&&L>=0)    {        if(N==0||L==0||C==0)        {            printf("0.000\n");            continue;        }        double minv = 0,maxv = acos(-1.0), midv;        double L2 = ( 1 + N * C ) * L;        while(maxv - minv > 1e-12)        {            midv = (minv + maxv) / 2;            if( 2 * L2 / L > midv / sin(midv / 2))                minv = midv;            else                    maxv = midv;        }        //printf("%.3lf\n",L2 / midv * (1-cos(midv / 2)));G++提交不要用prinf("lf")    }    return 0;}//法二:三分#include <cmath>#include <cstdio>#include <string>#include <cstring>#include <iomanip>#include <iostream>#include <algorithm>using namespace std;const double eps = 1e-10;const double PI = 3.1415926535897932384626433832795;double L,C,N,a,s,r,rad,ans;double Calc(double x) { return fabs(a*x-s*sin(x)); }void Search() {    double l,r,mid,midmid,mVal,mmVal;    l = 0,r = PI/2.0;    while(r-l>=eps)    {        mid = (l+r)/2.0;midmid = (mid+r)/2.0;        mVal = Calc(mid);mmVal = Calc(midmid);        if(mVal > mmVal)        {            rad = midmid;            l = mid;        }        else if(mVal < mmVal)        {            rad = mid;            r = midmid;        }        else        {            rad = (mid+midmid)/2.0;            l = mVal;            r = mmVal;        }    }    ans = s/rad*(1.0-cos(rad));    printf("%.3lf\n",ans);//G++提交不要用prinf("lf")}int main() {    //freopen("input.in","r",stdin);    while(~scanf("%lf %lf %lf",&L,&N,&C))    {        if(L<0) break;        if(N==0||L==0||C==0)        {            printf("0.000\n");            continue;        }        s = (1.0+N*C)*L/2.0;        a = L/2.0;        Search();    }    return 0;}


3 0
原创粉丝点击