1. 程式人生 > 實用技巧 >2020 Multi-University Training Contest 3 1008 Triangle Collision

2020 Multi-University Training Contest 3 1008 Triangle Collision

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=6798

題意:一個邊長為L的等邊三角形,平面座標系的原點位於三角形底邊上的中點,三角形裡有一個小球的座標為(x,y),並在水平方向上有初始速度vx,在豎著方向上有初始速度vy,小球與三角形的邊相撞會反彈,並且速度不會變,讓你求小球與三角形相碰k次的時間。

思路:可以把三角形的三條邊當做鏡子,小球反彈可以看做在鏡子中遇到,鏡子中是有無數的等邊三角形的,然後二分時間,看小球穿過所以三角形的邊數。對於水平方向的底邊,只要看小球的豎著方向上的速度,很好算。對於其他兩條斜邊,只要將座標點繞等邊三角形的中心點分別旋轉 120,240 度就可以演算法碰撞次數。

#include<bits/stdc++.h>
using namespace std;
const double EPS=1e-6;
const double PI=4.0*atan(1.0);
const double base=2*PI/3;
double L,vx,vy,x,y,h;
int k;
pair<double,double> get_point(const pair<double,double> &a,const double &rad)
{
    return make_pair(a.first*cos(rad)-(a.second-h/3)*sin(rad),a.first*sin(rad)+(a.second-h/3)*cos(rad)+h/3);
}
bool ck(double times)
{
    long long has=0;
    has+=abs(floor(get_point(make_pair(x+vx*times,y+vy*times),base*0).second/h));
    has+=abs(floor(get_point(make_pair(x+vx*times,y+vy*times),base*1).second/h));
    has+=abs(floor(get_point(make_pair(x+vx*times,y+vy*times),base*2).second/h));
    return has>=k;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>L>>x>>y>>vx>>vy>>k;
        h=L*sqrt(3)/2;
        double l=0,r=1e11;
        while(r-l>EPS)
        {
            double mid=(l+r)/2;
            if(ck(mid))
                r=mid;
            else
                l=mid;
        }
        printf("%.8lf\n",(l+r)/2);
    }
}