1. 程式人生 > >D-Keiichi Tsuchiya the Drift King 2018焦作 解析幾何

D-Keiichi Tsuchiya the Drift King 2018焦作 解析幾何

題目連結:哆啦A夢傳送門

題意:給出寬為a,長為b的車,有一條半徑為r,角度為d的拐彎軌道,讓你求出軌道的寬度,滿足儘可能的小。

題解:

我們先上幅圖:

 

看著這幅圖說話,題目又說,車是沿著軌道相切著漂移的,我們要想軌道盡可能的小,其實只是車左下角頂點D為基準,繞原點O旋轉的,當D點旋轉到以原點O成水平線之後軌道距離已經固定好了,就以半徑為OD旋轉,是的,我們這裡說的是水平線之後,那麼之前的呢?我們還不確定,因為水平線之前的軌道距離肯定比OD小,看圖就知道了,當我們旋轉的角度是{\color{Red} \alpha},這個{\color{Red} \alpha }就是題目說的d(因為是整體漂移的),而移到水平線的角度是{\color{Red} \beta },那麼移到D'

,顯然軌道距離小於OD,那麼我們要求此時的軌道距離,只要知道距離s就行了,我們將OD-s就是最後的結果,根據題目給的資料,

我們角{\color{Red} \gamma }可以很容易求出,{\color{Red} \gamma} =90-(180-(\beta -\alpha ))/2={\color{Red} (\beta -\alpha )/2}, 長度 由余弦定理可以很容易求出。

{\color{Red} \gamma }和長度t 都知道了,那麼在直角三角形,顯然最終的答案就是 {\color{Red} t*sin(\gamma )}

 

程式碼所示:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>

using namespace std;

const double PI=acos(-1.0);

const double esp=1e-10;
int dcmp(double x)
{
    if(fabs(x)<esp) return 0;
    else return x<0?-1:1;
}
int main()
{

    int ncase;
    scanf("%d",&ncase);

    while(ncase--)
    {
        double a,b,r,d;
        scanf("%lf%lf%lf%lf",&a,&b,&r,&d);

        double maxl=sqrt(b*b+(a+r)*(a+r));

        d=d*PI/180; ///轉化成弧度
        double anglemax=asin(b/maxl); ///求出beita


        if(dcmp(d-anglemax)>=0) printf("%.12f\n",maxl-r); ///說明移動後的點D'在水平線之後,故直接輸出就行了
        else{
            double angle=anglemax-d;

            ///餘弦定理求距離t
            double t=sqrt(maxl*maxl*2-2*maxl*maxl*cos(angle));

            ///求角度afa
            double co=angle/2;
            double s=t*sin(co);
//            printf("t=%f,angle=%f,s=%f,co=%f\n",t,angle,s,co);

            printf("%.12f\n",maxl-r-s);///減去s就行了

        }

    }
    return 0;
}