这道题比较考思维吧 首先 在三角形内部的反射 去求反射角比较麻烦 时间上也不允许 我们要利用反射的原理 把这个平面衍生成一个由正三角形 镶嵌构成的平面 那第k次碰撞就是 由这个球的坐标 及其速度 构成的射线 与平面内等边三角形的第k次相交 其他博客图很多 可以去看看
然后 我们二分一个时间 看这个时间 与整个平面有几个交点
首先看 和x轴平行的线 容易得出 交点个数为
floor的意思是 取小于等于当前小数的最大整数
另外两种 我们可以将坐标点 分别绕 等边三角形的中心 旋转 120度或者240度 即可 (等价于旋转坐标轴 变成以三角形的某条底边为x轴 对应的高为y轴的坐标系)
#include<bits/stdc++.h>
using namespace std;
double h,L,x,y,vx,vy;
int k;
const double eps = 1e-6;
const double pi = acos(-1);
const double base = 2*pi/3;
#define pa pair<double,double>
typedef long long ll;
ll solve(pa pt){
return abs(floor(pt.second/h));
}
pa rot(double x,double y,double rad){
return make_pair(x*cos(rad)-(y-h/3)*sin(rad),x*sin(rad)+(y-h/3.0)*cos(rad)+h/3);
}
bool check(double ti){
double nx=x+ti*vx,ny=y+ti*vy;
return (solve(rot(nx,ny,0*base))+solve(rot(nx,ny,1*base))+solve(rot(nx,ny,2*base)))>=(ll)k;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%lf%lf%lf%lf%lf%d",&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(check(mid)) r=mid;
else l=mid;
}
printf("%.8lf\n",(l+r)/2);
}
return 0;
}