题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6798
题意:给你一个等边三角形的坐标,以及等边三角形内运动的球的坐标和速度,当这个球在三角形碰撞到一条边反射时,反射角等于入射角,且速度不会变,即没有碰撞损失,现在让你求出第k次碰撞的时间。
题解:这个题的难点在于怎么把题意转换成比较好求的方法。
官方题解给的方法是把这个等边三角形不断对称,直至铺完整个平面。
这样就不用考虑反射了。题意就转换成了小球的运动轨迹会穿过多少轨迹线,不难发现只有与x轴平行的线比较好处理,
用y轴的运动距离除以三角形的高就是答案。
对于其他两个边,考虑把坐标轴旋转120度和240度,这样就转换成了第一个类型。
这样我们直接二分去枚举时间,判断是否符合题意就行了。
官方题解:
代码实现:
#include <bits/stdc++.h> #define db double #define ll long long using namespace std; const db eps = 1e-6; const db g3=sqrt(3); db H; ll calc(db y0,db vy,db t){db y=y0+vy*t;if(vy>=0) return abs(floor(y/H));else return abs(1-ceil(y/H)); } db L,x,y,vx,vy; ll judge(db t){return calc(y,vy,t)+calc(fabs((y+g3*x-H)/2.0),-g3*vx/2.0-vy/2.0,t)+calc(fabs((-y+g3*x+H)/2.0),g3*vx/2.0-vy/2.0,t); } int main(){ll k;int T;scanf("%d",&T);while(T--){scanf("%lf%lf%lf%lf%lf%lld",&L,&x,&y,&vx,&vy,&k);H=g3*L/2.0;db l=0,r=1e11,m;while(r-l>eps){m=(l+r)/2.0;if(judge(m)>=k) r=m;else l=m;}printf("%.6lf\n",m);}return 0; } /* 4 4000 0 1732 1000 0 1 4000 0 1732 1000 0 1000000 4000 0 1234 0 -1 1 4000 -1000 1 0 1000 925469 */