tozangezan's diary

勝手にソースコードをコピペして利用しないでください。

SRM 347 Div1 Easy

あんまりいい解法とはいえないが…

概要
動く2つの飛行機の初期座標、速さがベクトルで与えられて、この2つの飛行機の距離がd以下になることがあるならばYESを、ないならばNOを出力せよ。

解法
t秒後の2つの飛行機の距離をDとおくと、、
D^2=(x1+vx1*t-x2-vx2*t)^2+(y1+vy1*t-y2-vy2*t)^2+(z1+vz1*t-z2-vz2*t)
ここで、x1-x2=X,vx1-vx2=VXというように置き換えてただひたすら変形すると、
D^2=(VX^2+VY^2+VZ^2)(t+(VX*X+VY*Y+VZ*Z)/(VX^2+VY^2+VZ^2))^2+X^2+Y^2+Z^2-{(VX*X+VY*Y+VZ*Z)^2/(VX^2+VY^2+VZ^2)}

ここで二次関数の範囲つき(非負全体)最小値になるので、
場合わけ(t^2の係数が0になるか、グラフの軸がy軸より左になるか)を考える。
上二つの場合なら最初が最小距離、ほかならX^2+Y^2+Z^2-{(VX*X+VY*Y+VZ*Z)^2/(VX^2+VY^2+VZ^2)}が最小距離。
あとはやるだけ。
たぶんもっとましな解法があるはず。

public class Aircraft{
	public String nearMiss(int []a,int []b,int[] c,int []d,int e){
		int X=a[0]-c[0],Y=a[1]-c[1],Z=a[2]-c[2];
		int VX=b[0]-d[0],VY=b[1]-d[1],VZ=b[2]-d[2];
		if(VX*VX+VY*VY+VZ*VZ==0){
			if(X*X+Y*Y+Z*Z<=e*e)return "YES";
			else return "NO";
		}else if((double)(VX*X+VY*Y+VZ*Z)/(double)(VX*VX+VY*VY+VZ*VZ)>0){
			if(X*X+Y*Y+Z*Z<=e*e)return "YES";
			else return "NO";
		}else{
			System.out.println(X*X+Y*Y+Z*Z-((double)(VX*X+VY*Y+VZ*Z)/(double)(VX*VX+VY*VY+VZ*VZ)));
			if(X*X+Y*Y+Z*Z-((double)(VX*X+VY*Y+VZ*Z)*(double)(VX*X+VY*Y+VZ*Z)/(double)(VX*VX+VY*VY+VZ*VZ))-0.0000001<=(double)(e*e))return "YES";
			else return "NO";
		}
	}
}