POJ 1905 题解(二分+几何)

题面

传送门

分析

这里写图片描述
如图:已知 A B = L , A B = L ( 1 + n C ) ,M为AB中点,N为圆上一点,且ON垂直于AB于M,求MN
设半径为 R , A O M = θ (弧度), M N = x
则可列出方程组
{ 2 R θ = L ( 1 + n c ) ( 1 ) R sin θ = L 2 ( 2 ) x = R ( 1 cos θ ) ( 3 )
若求出 θ 便可以求出x,所以我们从 θ 入手,尝试解上面的方程组
由(1)(2)式得 θ sin θ = 1 + n C
本人数学不好,求不出上面的方程的解析解(如果有解析解可以在评论中指出)
于是采用二分的方法来近似求根
显然 0 < θ π 2
由图知 θ 越大, 1 + n C
我们二分 θ ,设二分中点为mid,端点为[L,R]并计算 m i d sin m i d ,若 m i d sin m i d > 1 + n C ,则寻找更小的,R=mid.否则寻找更大的,L=mid

还有几个细节:
1. π 一定要很精确,否则会WA
2.设定的二分误差要尽量小

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define eps 1e-11
#define pi 3.141592653589793
using namespace std;
double L,n,C,theta,x;
int main(){
    while(scanf("%lf %lf %lf",&L,&n,&C)!=EOF){
        if(L==n&&n==C&&C==-1) break;
        if(n*C==0){
            printf("0.000\n");
            continue;
        } 
        double l=eps,r=pi/2;//用弧度表示角 
        while(fabs(l-r)>eps){
            double mid=(l+r)/2;
            double hu=mid/sin(mid);
            if(hu>1+n*C) r=mid;
            else l=mid;
        }
        theta=l;
        double R=L/(2*sin(theta));
        printf("%.3f\n",R*(1-cos(theta)));
    } 
} 

猜你喜欢

转载自blog.csdn.net/oier_forever/article/details/80684682