Problem:
忍者のビル登り

忍者のあつしさんは、毎日朝早くから夜遅くまで忍者ビルの屋上から町を警備しています。この忍者ビルは、隣接する 2 つの同じ階数のビルであり、あつしさんは警備のために、ビルとビルの間をジャンプしながら屋上へ向かうことを日課としています。

この 2 つのビルは頻繁に清掃が行われるため、ビル登りの助けとなるはしごや障害となる滑りやすい部分があります。 しかも、はしごや滑りやすい部分の位置は毎日変わります。 そのためあつしさんは、屋上へ向かう方法を毎日考えなければいけません。

あつしさんは二つ並んだ同じ階数のビルの壁を跳び移りながら、ビルの屋上を目指します。ジャンプ
はどちらか一方のビルの1階から始められます。向かい側のビルへジャンプするときには、同じ階・1つ上の階・2 つ上の階の、いずれかに飛び移ることができます。

壁には以下の 3 種類があり、それぞれの壁にジャンプした後の移動が決まっています。

0. 普通の壁: 上下の移動はしない。次のジャンプはそこから行う。

1. はしご: はしごは 2 つ以上の階にまたがってかかっており、今いるはしごの一番上まで移動する。次のジャンプはそこから行う。

2. すべる壁: 普通の壁かはしごの一番上まで滑り落ちる。次のジャンプはそこから行う。

また、壁は 1 階から屋上のすぐ下の最上階まであり、屋上へはそのビルの最上階からのみ行くことが
できます。また、ビルの最下階の壁はすべる壁にはなりません。

2 つのビルの階数 n と 2 つのビルの壁の種類を入力とし、最少で何回目のジャンプで最上階までたどり着き、屋上まで行くことができるかを出力するプログラムを作成してください。なお、どちらのビルの屋上にたどり着いてもよいものとします。ただし、あつしさんがどちらのビルの屋上へもたどり着けない場合は“NA”と出力してください。

Input

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

n
a1 a2 ... an
b1 b2 ... bn

１行目にビルの階数 n (3 ≤ n ≤ 100) が与えられます。２行目に１ つ目のビルの 1 階から n 階までの壁の情報 ai、３行目に２つ目のビルの 1 階から n 階までの壁の情報 bi が与えられます。ai, bi はi 階目の壁の情報を表し、0 が普通の壁、1 がはしご(i 階と i+1 階にまたがる)、2 がすべる壁を表します。

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

Output

入力データセットごとに、ジャンプの回数を１行に出力します。

Sample Input

8
0 0 0 2 2 2 0 0
1 1 1 1 0 0 0 0
4
1 1 2 2
0 0 2 2
0

Output for the Sample Input

4
NA

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace _0230
{
    class Program
    {
        enum Wall { Normal, Ladder, Slip }

        class State
        {
            public int Building { get; set; }
            public int Floor { get; set; }
            public int MoveTimes { get; set; }
            public State(int building, int floor, int moveTimes)
            {
                Building = building;
                Floor = floor;
                MoveTimes = moveTimes;
            }
        }

        public static int[][] building;

        static void Main(string[] args)
        {
            while (true)
            {
                int n = RInt();
                if (n == 0) break;
                Init(n);
                Console.WriteLine(CalcMoveTimes());
            }
        }

        private static void Init(int n)
        {
            building = new int[2][];
            for (int i = 0; i < building.Length; i++) building[i] = RArInt();
        }

        private static string CalcMoveTimes()
        {
            bool[][] closed = new bool[building.Length][];
            Queue<State> q = new Queue<State>();

            for (int i = 0; i < building.Length; i++)
            {
                closed[i] = new bool[building[i].Length];

                int s = 0;
                if (building[i][0] == (int)Wall.Ladder) s = GetDest(i, 0, (int)Wall.Ladder);       
                q.Enqueue(new State(i, s, 0));
                closed[i][s] = true;
            }

            while (q.Count() > 0)
            {
                State state = q.Dequeue();
                if (state.Floor == building[0].Length - 1) return state.MoveTimes.ToString();

                for (int i = 0; i < 3; i++)
                {
                    if (state.Floor + i > building[0].Length - 1) continue;

                    int nextBuligind = state.Building ^ 1;
                    int nextFloor = state.Floor + i;

                    if (building[nextBuligind][nextFloor] != (int)Wall.Normal)
                    {
                        nextFloor = GetDest(nextBuligind, nextFloor, building[nextBuligind][nextFloor]);
                    }

                    if (!closed[nextBuligind][nextFloor])
                    {
                        q.Enqueue(new State(nextBuligind, nextFloor, state.MoveTimes + 1));
                        closed[nextBuligind][nextFloor] = true;
                    }
                }
            }
            return "NA";
        }

        private static int GetDest(int buildNum, int x, int wall)
        {
            if (wall == (int)Wall.Ladder)
            {
                for (int i = x + 1; i < building[buildNum].Length; i++)
                {
                    if (building[buildNum][i] != (int)Wall.Ladder) return i - 1;
                }
                return building[buildNum].Length - 1;
            }
            else
            {
                for (int i = x - 1; i >= 0; i--)
                {
                    if (building[buildNum][i] != (int)Wall.Slip) return i;
                }
                return 0;
            }
        }

        static string RSt() { return Console.ReadLine(); }
        static int RInt() { return int.Parse(Console.ReadLine().Trim()); }
        static long RLong() { return long.Parse(Console.ReadLine().Trim()); }
        static double RDouble() { return double.Parse(Console.ReadLine()); }
        static string[] RArSt(char sep = ' ') { return Console.ReadLine().Trim().Split(sep); }
        static int[] RArInt(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Trim().Split(sep), e => int.Parse(e)); }
        static long[] RArLong(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Trim().Split(sep), e => long.Parse(e)); }
        static double[] RArDouble(char sep = ' ') { return Array.ConvertAll(Console.ReadLine().Trim().Split(sep), e => double.Parse(e)); }
        static string WAr<T>(IEnumerable<T> array, string sep = " ") { return string.Join(sep, array.Select(x => x.ToString()).ToArray()); }
    }
}