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;
}