土下座しながら探索中

主に競技プログラミング

UVa 11326 : Laser Pointer

問題リンク:http://uva.onlinejudge.org/external/113/11326.html

問題概要:
H*Wの部屋がある
壁は全て鏡である
部屋の左下からレーザービームを角度thetaで打つ
そのレーザービームは部屋の右の壁のある一点にぶつかる
その時のレーザービームの長さAと直接その一点にむけてレーザービームを打った時の長さBを求めよ

解法:
鏡系の問題ではよくある、部屋を複数つなげるあれをする

上の図のxは正弦定理で求める亊ができる(tanを使ってもできる)
yはsqrt(L*L+X*X)
このyは問題文でいうAにあたる
Bはレーザーが壁に当たった回数が偶数か奇数かで変わる
偶数ならsqrt(L*L+(X%W)*(X%M))
奇数ならsqrt(L*L+(W-X%W)*(W-X%W))
ここで、XとWはdoubleなのでfmodという関数を使用する

コード:

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)

using namespace std;

inline double toRad(double t){ return t*M_PI/180.0; }

int main()
{
  int T;
  while(cin >> T)
    {
      while(T--)
       {
	  double L,W,theta1;
	  cin >> L >> W >> theta1;
	  theta1 = toRad(theta1);
	  double theta2 = toRad(180.0) - (toRad(90.0)+theta1);
	  double X = L*sin(theta1)/sin(theta2);
	  //double X = L * tan(theta1);
	  double A = sqrt(L*L+X*X);
	  int cnt = X/W;
	  double R = ((cnt&1)?W-fmod(X,W):fmod(X,W));
	  double B = sqrt(L*L+R*R);
	  printf("%.3lf\n",A/B);
	}
    }
  return 0;
}