题目链接: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); } }