No.61 リベリオン - yukicoder
- 鏡面反転のアイデアは思いついたけど、反転後の Mx,My の座標をどう求めればいいかわからなかった。
- そっちの解法は Extra で学ぶとして、この問題の制約ではシミュレーションで十分だった。
- 格子点ごとの移動をさせるために最大公約数を計算するのと、一秒間の移動で反転が複数回行われるケースに対応するのがポイントだと思う。
class Rebellion {
public:
void solve(void) {
int Q;
cin>>Q;
REP(q,Q)
{
int W,H,Mx,My,Hx,Hy;
ll D,Vx,Vy;
cin>>W>>H>>D>>Mx>>My>>Hx>>Hy>>Vx>>Vy;
ll k = gcd(abs(Vx),abs(Vy));
Vx /= k;
Vy /= k;
D = min(1050LL, D*k);
int x,y;
x = Hx;
y = Hy;
bool hit = false;
for (int d = 1; d <= D; ++d)
{
x += Vx;
y += Vy;
while (true)
{
if (x < 0) { Vx *= -1; x = -x; continue; }
if (x > W) { Vx *= -1; x = 2*W-x; continue; }
if (y < 0) { Vy *= -1; y = -y; continue; }
if (y > H) { Vy *= -1; y = 2*H-y; continue; }
break;
}
if (x == Mx && y == My)
{
hit = true;
break;
}
}
if (hit)
cout<<"Hit"<<endl;
else
cout<<"Miss"<<endl;
}
}
};