当前位置: 代码迷 >> 综合 >> 杭电多校第三场 Triangle Collision——思维+二分
  详细解决方案

杭电多校第三场 Triangle Collision——思维+二分

热度:41   发布时间:2024-02-20 09:09:41.0

题目链接: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
*/