codeforces链接  戳这里

 

比赛中想了好久 没想到弦长公式  没做出来  真的是。。。。。。唉

解题思路:

(原谅我的画图技术(逃~

 

小车通过管道  管道的宽度 取决于这个过程中 小车的角距离圆心最远的时刻

那么这个最远的情况  是什么样子的呢

就是小车和弯道相切并且切点和小车的一个角重合的时候  此时 对应的角就是距离最远的位置

如上图 图上这种情况我们其实很好求 

题上给了 a b d r   那么勾股定理  显然最远的距离maxw=sqrt ( (r+a)^2 + b^2 )

而  答案  w = maxw - r

但是还有另外一种情况

我们把 r 和 a 垂直时(r+a)与 b 形成的 直角三角形 中的那个靠近圆心的锐角称作 t1

如图

 

上面的图是 t1< d 的情况   当 t1 > d的情况 那么就和刚才不一样了

如下图

d 是弯道的角度    当t1>d的时候 

你用刚才的方法 勾股定理求出来的是图上那条绿色的线的长度 maxw

那么再用它减去r   得到的距离 如下图

显然 这不是管道应有的宽度  因为这条线并不垂直于管道

那么怎么办呢

其实 在小车通过管道的过程中  那个最远的点到圆心的距离(也就是这条绿线)是不变的

也就意味着 这个点的轨迹 其实形成了一个圆 ,一个半径为 maxw的圆

那么当轨迹垂直于管道的时候    

如下图  就是橙色线的情况(当然 在t1>d的情况下 轨迹是不可能垂直的  不存在这种情况 我们只是辅助分析)

橙色线和绿色线相等 构成了一个扇形  形成的圆心角是 t1 - d  我们记作 t2

知道了圆心角和半径 那么对着的弦长L也就可以求出来了

(公式:圆心角为a,圆半径为R,则圆心角所对弦长L=2R*sin(a/2)  )

如图  弦长L是红色的线

既然知道了 t2  橙线又与绿线相等 我们就可以得到 t3了(L与橙线的夹角)

而知道了 t3和L  我们就可以求出 p的长度了(p就是多的那一小段)  如下图

求出了p        maxw - p - r就是答案

代码如下

代码中各个变量与上面的讲解是 一 一对应的。

需要注意的:

1、角度转弧度制: 1度= π/180   ,弧度转角度 : 1弧度=180/π

2、圆心角为a,圆半径为R,则圆心角所对弦长L=2R*sin(a/2)

#include<stdio.h>
#include<math.h>
#include<iostream>
#include<algorithm>
using namespace std;
const double PI=acos(-1.0);
double a,b,r,d;
int T;
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%lf%lf%lf%lf",&a,&b,&r,&d);

        double maxw=sqrt( (r+a)*(r+a)+ b*b );//勾股定理

        //角度转化弧度制   1度 = PI/180
        double dc=d*PI/180.0;

        //车子漂移时 最远点情况 形成的角度
        double t1=acos((a+r)/maxw);

        if((dc-t1)>0){
            printf("%.12f\n",maxw-r);
        }
        else{
            double t2=t1-dc;

            //设圆心角为a,圆半径为R,则圆心角所对弦长L=2R*sin(a/2)
            double L=2*maxw*sin(t2/2);

            double t3=(PI-t2)/2;//三角形内角和180度 转成弧度制 是PI
            //求出少的那点边长

            double p=L*cos(t3);
            printf("%.12f\n",maxw-p-r);
        }

    }
    return 0;
}