Problem:
Problem B: 平安京ウォーキング

平安京は、道が格子状になっている町として知られている。

平安京に住んでいるねこのホクサイは、パトロールのために毎日自宅から町はずれの秘密の場所まで行かなければならない。しかし、毎日同じ道を通るのは飽きるし、後を付けられる危険もあるので、ホクサイはできるだけ毎日異なる経路を使いたい。その一方で、ホクサイは面倒臭がりなので、目的地から遠ざかるような道は通りたくない。

平安京のあちこちの道にはマタタビが落ちていて、ホクサイはマタタビが落ちている道を通ることができない。そのような道を通るとめろめろになってしまうからである。幸いなことに、交差点にはマタタビは落ちていない。

ホクサイは、自宅から秘密の場所までの可能な経路の数を知りたい。ここで、ホクサイの自宅は (0, 0) にあり、秘密の場所は(gx, gy)にある。道は x = i (i は整数), y = j (j は整数) に格子状に敷かれている。

Input

入力の1行目には、秘密の場所の座標 (gx, gy) が与えられる。これらはいずれも1以上15以下の整数で、空白1個で区切られて与えられる。 2行目にはマタタビが落ちている区間の数 p (0 ≤ p ≤ 100) が与えられ、続くp行にはマタタビが落ちている区間が1行に1区間ずつ与えられる。 p個の区間は互いに異なる。 1区間は x1 y1 x2 y2 の形で表され、(x1, y1) と (x2, y2) を端点とする、x軸またはy軸に平行な長さ1の線分である。 x1, x2 は [0, gx] の範囲にあり、y1, y2 は [0, gy] の範囲にある。

Output

可能な経路の数を出力せよ。可能な経路が1つもない場合は "Miserable Hokusai!" と1行に出力せよ。

Notes on Submission

上記形式で複数のデータセットが与えられます。入力データの 1 行目にデータセットの数が与えられます。各データセットに対する出力を上記形式で順番に出力するプログラムを作成して下さい。

Sample Input

4
2 2
0
1 1
2
0 0 0 1
0 0 1 0
4 3
4
1 0 0 0
3 3 4 3
4 1 4 0
0 2 0 3
15 15
0

Output for the Sample Input

6
Miserable Hokusai!
5
155117520

Solution in JAVA (judge verdict: Accepted)

import java.io.*;
import java.util.*;

public class Main {
    Scanner sc;
    int[][] field;
    int gx, gy;
    int p;
    boolean[][][][] matatabi;

    int dataset;

    Main() {
        sc = new Scanner(System.in);
        dataset = sc.nextInt();
    }

    void init() {
        gx = sc.nextInt();
        gy = sc.nextInt();
        field = new int[gy+1][gx+1];
        matatabi = new boolean[gy+1][gx+1][gy+1][gx+1];

        p = sc.nextInt();
        for (int i = 0; i < p; i++) {
            int x1 = sc.nextInt();
            int y1 = sc.nextInt();
            int x2 = sc.nextInt();
            int y2 = sc.nextInt();
            matatabi[y1][x1][y2][x2] = true;
            matatabi[y2][x2][y1][x1] = true;
        }
    }

    void run() {
        for (int _i = 0; _i < dataset; _i++) {
            init();
            field[0][0] = 1;
            for (int i = 1; i <= gx; i++) {
                if (matatabi[0][i-1][0][i]) break;
                field[0][i] = 1;
            }
            for (int i = 1; i <= gy; i++) {
                if (matatabi[i-1][0][i][0]) break;
                field[i][0] = 1;
            }

            for (int i = 1; i <= gy; i++) {
                for (int j = 1; j <= gx; j++) {
                    if (matatabi[i][j-1][i][j] && matatabi[i-1][j][i][j]) {
                        field[i][j] = 0;
                    } else if (matatabi[i][j-1][i][j]) {
                        field[i][j] = field[i-1][j];
                    } else if (matatabi[i-1][j][i][j]) {
                        field[i][j] = field[i][j-1];
                    } else {
                        field[i][j] = field[i-1][j] + field[i][j-1];
                    }
                }
            }

            if (field[gy][gx] == 0) {
                System.out.println("Miserable Hokusai!");
            } else {
                System.out.println(field[gy][gx]);
            }
        }
    }

    public static void main(String[] args) {
        new Main().run();
    }
}