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 JAVA (judge verdict: Accepted)

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Set;

public class Main {
    Scanner sc = new Scanner(System.in);

    void run() {
        for (;;) {
            // 1 行目 ビルの階数 n(整数)
            // 2 行目 1 つ目のビル a の 1 階から n 階までの壁の情報 a1 a2 ... an(すべて整数;半角空白区切り)
            // 各 ai は、i 階目の壁の情報を表し、意味は以下のとおりです。
            // 0:普通の壁
            // 1:はしご(i 階と i+1 階にまたがる)
            // 2:すべる壁
            // 3 行目 2 つ目のビル b の 1 階から n 階までの壁の情報 b1 b2 ... bn(すべて整数;半角空白区切り)
            int n = sc.nextInt();
            if (n == 0)
                break;
            int fs[][] = new int[2][n];
            for (int i = 0; i < n; i++) {
                fs[0][i] = sc.nextInt();
            }
            for (int i = 0; i < n; i++) {
                fs[1][i] = sc.nextInt();
            }
            Queue<Data> q = new LinkedList<Data>();
            int sfa = 0;
            int sfb = 0;
            if (fs[0][0] == 1)
                while (sfa + 1 < n && fs[0][sfa + 1] == 1)
                    sfa++;
            if (fs[1][0] == 1)
                while (sfb + 1 < n && fs[1][sfb + 1] == 1)
                    sfb++;
            q.add(new Data(0, sfa, 0));
            q.add(new Data(1, sfb, 0));
            Set<String> set = new HashSet<String>();
            boolean na = true;
            while (!q.isEmpty()) {
                Data d = q.poll();
                int b = d.b;
                int f = d.f;
                if (set.contains(b + " " + f))
                    continue;
                set.add(b + " " + f);
                int t = d.t;
                if (f == n - 1 && fs[b][n - 1] != 2) {
                    System.out.println(t);
                    na = false;
                    break;
                }
                int nb = b ^ 1;
                for (int i = 0; i < 3; i++) {
                    // 向かい側のビルへジャンプするときには、
                    // 同じ階・1つ上の階・2 つ上の階の、いずれかに飛び移ることができます。
                    if (i + f >= n)
                        continue;
                    int nf = f + i;
                    switch (fs[nb][i + f]) {
                    case 0:
                        q.add(new Data(nb, nf, t + 1));
                        break;
                    case 1:
                        while (nf + 1 < n && fs[nb][nf + 1] == 1)
                            nf++;
                        q.add(new Data(nb, nf, t + 1));
                        break;
                    case 2:
                        while (fs[nb][nf] == 2)
                            nf--;
                        q.add(new Data(nb, nf, t + 1));
                        break;
                    }
                }

            }
            if (na)
                System.out.println("NA");
        }
    }

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

class Data {
    int b;
    int f;
    int t;

    Data(int b, int f, int t) {
        this.b = b;
        this.f = f;
        this.t = t;
    }

    public String toString() {
        return b + " " + f + " " + t;
    }
}