TopCoder SRM 323 Div1 Medium Survived
問題
x,y平面上の原点に人がいる。
原点から、点(x,y)へ泳いで行きたい。
この人の泳ぐ速さは最大でVである。
水は、x軸の正の向きに、一様で速度Uで流れている。
この人が(x,y)まで着くのにかかる時間を求めよ。
(x,y)に辿り着けない場合は-1を返せ。
制約条件
-100≦x,y≦100
0≦U,V≦100
方針
流れのない状態で、泳ぐ向きの角をtとする。
流れがない状態では泳ぎの速度のベクトルは(Vcos(t),Vsin(t) )
流れがある状態での速度のベクトルは(Vcos(t)+U,Vsin(t) )
このベクトルが(x,y)に平行になればよいので、
Vxsin(t)=Vycos(t)+yU
ここから、三角関数の合成を使って、√(x^2+y^2) sin(t-α)=yU/V
ただしαはtanα=y/xを満たす角
となって、tが求まる。
tが求まれば、速度ベクトルが求まり、目的地までの時間がもとまる。
上の方程式が解をもたない場合や、
速度ベクトルと(x,y)のベクトルが反平行になった場合は、辿り着くことができない。
コーナーケースが多すぎて通すの大変だった。
ソースコード
double sq(double x){ return x*x; } class Survived { public: double minTime(int x, int y, int V, int U) { if(x*x+y*y==0)return 0; double a=sq(V*x)+sq(V*y); if(V==0&&y*U==0){ if(U==0||y!=0||x<0)return -1; return x*1.0/U; } if(a<sq(y*U))return -1; double t=asin(y*U/sqrt(a))+atan2(y,x); double dy=V*sin(t), dx=V*cos(t)+U; if(x*dx+y*dy<EPS)return -1; return hypot(x,y)/hypot(dy,dx); } };