Problem:
宇宙船 UAZ アドバンス号

恒星歴 2005.11.5。あなたは宇宙船 UAZ アドバンス号の艦長として敵の宇宙船と交戦しようとしています。 幸い敵の宇宙船はまだこちらに気付かずに静止しています。また、すでに敵の宇宙座標は判明しており強力な直線のビームを放つ「フェザー砲」は発射準備を完了しています。あとは、発射命令を出すばかりです。

ところが、宇宙空間には、敵の設置したエネルギーバリアが存在しています。バリアは三角形をしており「フェザー砲」のビームをはね返してしまいます。また、ビームがバリアに当たれば敵に気付かれて逃げられてしまいます。事前に命中すると判定できなければ、発射命令は出せません。

そこで、UAZ アドバンス号、敵、バリアの位置の宇宙座標(3次元座標 x, y, z) を入力して、ビームがバリアをさけて敵に命中する場合は "HIT"、バリアに当たってしまう場合"MISS"と出力するプログラムを作成してください。

ただし、バリアはアドバンス号から 3 角形に見えるものだけが対象であり、線分につぶれて見えるものはないものとします。また、バリアは 3 角形の頂点を含む境界でも有効であり、ビームをはね返すものとします。また、敵がバリア内にいる場合は"MISS"と出力して下さい。

Input

入力データの形式は以下のとおりです：

1 行目は、UAZ アドバンス号の座標 (x, y, z) (整数、半角空白区切り)

2 行目は、敵の座標 (x, y, z) (整数、半角空白区切り)

3 行目は、バリアの頂点 1 の座標 (x, y, z) (整数、半角空白区切り)

4 行目は、バリアの頂点 2 の座標 (x, y, z ) (整数、半角空白区切り)

5 行目は、バリアの頂点 3 の座標 (x, y, z ) (整数、半角空白区切り)

Output

HIT または MISS と１行に出力してください。

Constraints

-100 ≤ x, y, z ≤ 100

UAZ アドバンス号と敵が同じ位置にいることはない。

Sample Input 1

-10 0 0
10 0 0
0 10 0
0 10 10
0 0 10

Output for the Sample Input 1

HIT

Sample Input 2

-10 6 6
10 6 6
0 10 0
0 10 10
0 0 10

Output for the Sample Input 2

MISS

Solution in JAVA (judge verdict: Wrong Answer)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class Main {
	private	static	BufferedReader	br = null;
	private	static	int				IX = 0;
	private	static	int				IY = 1;
	private	static	int				IZ = 2;
	private	static	double			ZR = 1e-9;

	static {
		br = new BufferedReader(new InputStreamReader(System.in));
	}
 
    /**
     * @param args
     */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		solve(parsePos());
	}

	private static void solve(int[][] pos) {
		boolean	bHit = true;

		if (!isEmpty(pos[2], pos[3], pos[4]) && !isVertical(pos[0], pos[1], pos[2], pos[3], pos[4])) {
			bHit = !isCross(pos[0], pos[1], pos[2], pos[3], pos[4]);
		}

		System.out.println(bHit?"HIT":"MISS");
	}

    private static boolean isCross(int[] m, int[] e, int[] a, int[] b, int[] c) {
		double[][]	mtr = new double[3][4];

		for (int i = IX; i <= IZ; i++) {
			mtr[i][0] = b[i]-a[i];	// s
			mtr[i][1] = c[i]-a[i];	// t
			mtr[i][2] = e[i]-m[i];	// u
			mtr[i][3] = e[i]-a[i];	// k
		}

		calc(mtr);

		return (ZR <= mtr[0][3] && ZR <= mtr[1][3] && ZR <= mtr[0][3]+mtr[1][3] && mtr[0][3]+mtr[1][3] <= 1.0 && ZR <= mtr[2][3] && mtr[2][3] <= 1.0);
	}

	private static void calc(double[][] aMatrix) {
		int nActRow = -1;
 
		for(int nCols = 0; nCols < aMatrix[0].length - 1; nCols++) {
			nActRow = -1;

			// 全ての行のnCols番目の列の要素が1になるように行の要素を除算する
			for(int nRols = nCols; nRols < aMatrix.length; nRols++) {
				if (Math.abs(aMatrix[nRols][nCols]) > ZR) {
					if (nActRow == -1) {
						nActRow = nRols;
					}

					for(int nLoop = aMatrix[0].length - 1; nLoop >= nCols; nLoop--) {
						aMatrix[nRols][nLoop] /= aMatrix[nRols][nCols];
					}
				}
			}

			// nActRowを上にもってくる
			if (nActRow != -1 && nActRow != nCols) {
				double[]	tmp  = aMatrix[nCols];
				aMatrix[nCols]   = aMatrix[nActRow];
				aMatrix[nActRow] = tmp;
				nActRow          = nCols;
			}

			// 全ての列の要素から最初に要素を1にした列の要素を減算する
			for(int nRols = 0; nRols < aMatrix.length; nRols++) {
				if (Math.abs(aMatrix[nRols][nCols]) > ZR && nRols != nActRow) {
					for(int nLoop = aMatrix[0].length - 1; nLoop >= nCols; nLoop--) {
						double  dWork = aMatrix[nRols][nCols] * aMatrix[nActRow][nLoop];
						aMatrix[nRols][nLoop] -= dWork;
					}
				}
			}
		}
	}

	private static boolean isVertical(int[] m, int[] e, int[] a, int[] b, int[] c) {
		int[]	ab = {b[IX]-a[IX], b[IY]-a[IY], b[IZ]-a[IZ]};
		int[]	ac = {c[IX]-a[IX], c[IY]-a[IY], c[IZ]-a[IZ]};
		int[]	em = {m[IX]-e[IX], m[IY]-e[IY], m[IZ]-e[IZ]};
		int[]	n  = {ab[IY]*ac[IZ]-ac[IY]*ab[IZ], ab[IZ]*ac[IX]-ac[IZ]*ab[IX], ab[IX]*ac[IY]-ac[IX]*ab[IY]};

		return (em[IX]*n[IX]+em[IY]*n[IY]+em[IZ]*n[IZ]) == 0;
	}

	private static boolean isEmpty(int[] a, int[] b, int[] c) {
		int[]	ab = {b[IX]-a[IX], b[IY]-a[IY], b[IZ]-a[IZ]};
		int[]	ac = {c[IX]-a[IX], c[IY]-a[IY], c[IZ]-a[IZ]};
		int		w1 = ab[IX]*ab[IX]+ab[IY]*ab[IY]+ab[IZ]*ab[IZ];
		int		w2 = ac[IX]*ac[IX]+ac[IY]*ac[IY]+ac[IZ]*ac[IZ];
		int		w3 = ab[IX]*ac[IX]+ab[IY]*ac[IY]+ab[IZ]*ac[IZ];

		return (w1*w2-w3*w3) == 0;
	}

	private static int[][] parsePos() {
		int[][]	pos = new int[5][3];

		for (int i = 0; i < pos.length; i++) {
			String		str = parseStdin();
			String[]	lns = str.split(" ");
			pos[i][IX] = Integer.parseInt(lns[IX]);
			pos[i][IY] = Integer.parseInt(lns[IY]);
			pos[i][IZ] = Integer.parseInt(lns[IZ]);
		}
 
		return pos;
	}

	private static String parseStdin() {
        String  stdin = null;
        
        try {
        	String  tmp = br.readLine();
        	if (tmp != null) {
            	if (!tmp.isEmpty()) {
            		stdin = tmp;
            	}
        	}
        }
        catch (IOException e) {}
 
        return stdin;
	}
}