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
",(l+r)/2);
    }
}

  

原文地址:https://www.cnblogs.com/zcb123456789/p/13399836.html