2018ICPC焦作D(幾何)---Keiichi Tsuchiya the Drift King
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;
}