Problem:
会津山スキー場の新企画

会津山スキー場の経営者である油木屋さんは、上級者向けとして障害物やジャンプ台を配置したコースを用意しました。コースにはいろいろな滑り方があり、シーズン中に全てのパターンの滑り方が出来た利用者には、プレゼントを贈ることになっています。

油木屋さんのために、コースの見取り図をもとに滑り方のパターン数を出力するプログラムを作ってあげましょう。

コースは上図のような X × Y 個のマスからなるグリッドで表されます。左上を原点とし、x 座標は右に行くにつれて大きくなり、y 座標は下にいくにつれて大きくなるものとします。

各滑り方のパターンは、最も高いところ(y = 1 、ただし障害物の無いところ) からスタートし、ゴール(y = Y) に向かって進んでいきます。グリッドのマス(x, y) にいる滑走者は、(x − 1, y + 1)、(x, y + 1)、 (x + 1, y + 1) のいずれかに移動することができます。マスには、障害物やジャンプ台があり、障害物のあるマスには進入できず、ジャンプ台があるマスに進入すると(x, y + 2) へ移動します。ただし、いちばん高いマス (y = 1 のマス) にはジャンプ台は存在せず、ジャンプ台のあるマスに進入する際には x 座標が同じマスからしか進入できません。コースの上端(y = 1) からスタートし、コースからはずれることなく下端を超えれば(y ≥ Y) 1つの滑り方とみなし、滑り終わります。

コースの情報を入力とし、滑り方の総数を出力するプログラムを作成してください。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロふたつの行で示されます。各データセットは以下の形式で与えられます。

X Y
c11 c21 ... cX1
c12 c22 ... cX2
:
c1Y c2Y ... cXY

1 行目にコースの大きさX, Y (1 ≤ X, Y ≤ 15) が与えられます。続く Y 行にコースの情報が与えられます。cij (0 , 1 , 2 のいずれか) はx = i, y = j のマスの情報を表す整数で、0 が移動可能なマス、1 が障害物があるマス、2 がジャンプ台があるマスを表します。

データセットの数は 50 を超えません。

Output

入力データセットごとに、コースの滑り方のパターン数を1行に出力します。

Sample Input

5 5
0 0 0 0 1
2 1 0 2 0
1 0 0 1 1
0 2 1 2 0
0 1 0 0 0
5 5
0 0 1 0 0
2 1 0 2 0
1 0 0 1 1
0 2 1 2 0
0 1 0 0 0
15 15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0

Output for the Sample Input

8
6
52694573

Solution in C# (judge verdict: Accepted)

using System;

public class Hello
{
    public static void Main()
    {
        while (true)
        {
            string[] line = Console.ReadLine().Trim().Split(' ');
            var w = int.Parse(line[0]);
            var h = int.Parse(line[1]);
            if (w == 0 && h == 0) break;
            var map = new int[h, w];
            for (int i = 0; i < h; i++)
            {
                string[] line2 = Console.ReadLine().Trim().Split(' ');
                for (int j = 0; j < w; j++) map[i, j] = int.Parse(line2[j]);
            }
            var dp = new int[h, w];
            goDP(map, dp);
            var ans = 0;
            for (int i = 0; i < w; i++)
            {
                ans += dp[h - 1, i];
                if (h-2 >= 0  && map[h - 2, i] == 2) ans += dp[h - 2, i];
            }
            Console.WriteLine(ans);
        }
    }
    public static void goDP(int[,] map, int[,] dp)
    {
        var h = dp.GetLength(0); var w = dp.GetLength(1);
        for (int i = 0; i < w; i++)
            if (map[0, i] == 0) dp[0, i] = 1;
        for (int i = 1; i < h; i++)
            for (int j = 0; j < w; j++)
                switch (map[i, j])
                {
                    case 0:
                        if (i - 2 >= 0 && map[i - 2, j] == 2) dp[i, j] += dp[i - 2, j];
                        if (map[i - 1, j] == 0) dp[i, j] += dp[i - 1, j];
                        if (j - 1 >= 0 && map[i - 1, j - 1] == 0) dp[i, j] += dp[i - 1, j - 1];
                        if (j + 1 <= w - 1 && map[i - 1, j + 1] == 0) dp[i, j] += dp[i - 1, j + 1];
                        break;
                    case 2:
                        if (map[i - 1, j] == 0) dp[i, j] = dp[i - 1, j];
                        if (i - 2 >= 0 && map[i - 2, j] == 2) dp[i, j] += dp[i - 2, j];
                        break;
                    default:
                        break;
                }
    }
}