2020杭電多校第三場 H - Triangle Collision - 計算幾何
阿新 • • 發佈:2020-07-29
Description
給定一個等邊三角形,三個頂點分別為 \((-L/2,0),(L/2,0),(0,\sqrt 3L/2)\)
一束光線從 \((x,y)\) 射出,速度為 \((v_x,v_y)\),遇到牆壁會反射,保證不會射到頂點上
問第 \(k\) 次碰撞的時間
Solution
二分答案,考慮求在已知時間內的碰撞次數
把三角形邊看成是鏡子,問題就轉化為在無限密鋪等邊三角形中的運動
考慮與 \(x\) 軸平行的線,這樣答案為 \(|\lfloor \frac y {\frac {\sqrt 3}{2} L} \rfloor|\)
然後通過繞中心旋轉 \(2\pi /3\) 使得斜邊成為平邊,然後重複上述過程即可
#include <bits/stdc++.h> using namespace std; #define int long long const int N = 1000005; const double pi = acos(-1); const double a = 120*pi/180; const double d = sqrt(3)/6; double l; int k; struct point { double x,y; point operator + (const point &b) { return {x+b.x, y+b.y}; } point operator * (double k) { return {k*x,k*y}; } } r,v; point rotate(point p,double a) { point res; res.x = p.x*cos(a) - p.y*sin(a); res.y = p.x*sin(a) + p.y*cos(a); return res; } point calc(point p) { p.y -= d*l; p = rotate(p,a); p.y += d*l; return p; } int eval(point p) { return abs(floor(2*p.y/sqrt(3)/l)); } int check(double tim) { int ans=0; point t=r+v*tim; ans+=eval(t); t=calc(t); ans+=eval(t); t=calc(t); ans+=eval(t); return ans; } void solve() { cin>>l>>r.x>>r.y>>v.x>>v.y>>k; double l=0,r=1e9; while(r-l>1e-6) { double mid=(l+r)/2; //cout<<"mid="<<mid<<" chk="<<check(mid)<<endl; if(check(mid)>=k) r=mid; else l=mid; } cout<<setiosflags(ios::fixed)<<setprecision(8)<<l<<endl; } signed main() { ios::sync_with_stdio(false); int t; cin>>t; while(t--) { solve(); } }