1. 程式人生 > >2018ICPC焦作D(幾何)---Keiichi Tsuchiya the Drift King

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