1. 程式人生 > 實用技巧 >2020 Multi-University Training Contest 3 - H. Triangle Collision(計算幾何)

2020 Multi-University Training Contest 3 - H. Triangle Collision(計算幾何)

題目連結:Triangle Collision

題意:在一個邊長為L的等邊三角形內有一顆小球,給出初始位置$(x,y)$和速度$(v_x,v_y)$,每次與三角形的三邊碰撞都為彈性碰撞,求第k次與邊碰撞是在什麼時候

思路:我們可以將三角形進行擴充套件,如下圖所示

可以看做小球在走直線,我們二分時間t,比較小球經過三邊的次數與k的大小即可

以求經過三角形的底邊為例,在t時間內,小球在y軸上運動的$v_y * t$,那麼在t時刻,小球的座標為$y+v_y * t$

如果$v_y >= 0$,即小球向上走,那麼經過三角形底邊的次數為$\left \lfloor \frac{y+v_y*t}{H} \right \rfloor$,H為三角形的高

如果$v_y<0$,即小球向下走,那麼經過三角形底邊的次數為$1-\left \lceil \frac{y+v_y*t}{H} \right \rceil$,注意此時$y+v_y*t$可能為負數,所以應該向上取整

對於另外的兩種邊,將座標和速度都翻轉一下,公式如下:

$y'=\frac{\left | H-\sqrt3 x-y \right |}{2}$,$v_y'=-\frac{\sqrt3}{2}v_x-\frac{1}{2}v_y$

$y'=\frac{\left | H+\sqrt3 x-y \right |}{2}$,$v_y'=\frac{\sqrt3}{2}v_x-\frac{1}{2}v_y$

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>

using namespace std;

typedef long long ll;

const double sq3 = sqrt(3);
const double eps = 1e-6;

int T;
ll k;
double L, x, y, vx, vy;

ll solve(double y, double vy, double
t) { double H = sq3 * L / 2, x = (y + vy * t) / H; if (vy >= 0) return abs(floor(x)); return abs(1 - ceil(x)); } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); scanf("%d", &T); while (T--) { scanf("%lf%lf%lf%lf%lf%lld", &L, &x, &y, &vx, &vy, &k); double H = sq3 * L / 2, l = 0, r = 100000000000; while (r - l > eps) { double mid = (l + r) / 2; ll a = solve(y, vy, mid); ll b = solve(abs(H - sq3 * x - y) / 2, -vy / 2 - sq3 * vx / 2, mid); ll c = solve(abs(H + sq3 * x - y) / 2, sq3 * vx / 2 - vy / 2, mid); if (a + b + c >= k) r = mid; else l = mid; } printf("%.8lf\n", l); } return 0; }