Problem:
11 パズル

太郎君は 8 パズルが大得意で休み時間などにいつも友達に並び替えてもらって遊んでいます。そんなとき、友達から「もっと複雑なパズルは解ける?」と聞かれたのですが、他のパズルはやったことはありません。どうやらその友達は自作で 11 パズルを作っていたみたいです。そのパズルは以下のような形をしています。

11 パズルは 11 枚の正方形のカードと、図 1 のような形の枠を使って行います。最初に 11 枚のカードを枠に入れます。すると 2 カ所の空きスペースができますので、この空きスペースに隣接したカードを動かすことができます。これを繰り返し、カードをきれいに整列して、図 2 の完成型にすることが 11 パズルの目的です。

太郎君はこのパズルに挑戦することにしました。ところが太郎君はこの 11 パズルをいとも簡単に解いてしまいました。そこで友達は「動かす数を一番少なくして解いてよ!」と無茶なことを言ってきました。太郎君は答えがわからないので、プログラムのできるあなたに 11 パズルを解くときの最小ステップ数を出すプログラムを作成してもらってから挑戦することにしました。このとき、2 カ所動かせるところがあるのですが、一つの数字を 1 スペース分移動させることを1ステップとして考えることとします。

11 パズルの初期状態を入力とし、11 パズルを解くときの最小ステップ数を出力するプログラムを作成してください。ただし、パズルを解くときの最小ステップ数が 20 ステップより多くかかってしまう場合は、「NA」と出力してください。パズルの状態は、一行目の情報から順に入力されるものとし、数字の 0 は空きスペースを表します。例えば、図 1 の状態を表す入力は以下のようになります。

6
2 1 3
10 5 7 0 8
9 4 11
0

Input

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

p1
p2 p3 p4
p5 p6 p7 p8 p9
p10 p11 p12
p13

i 行目にパズルの i 行目の情報 pi (0 ≤ pi ≤ 11) が空白区切りで与えられます。

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

Output

データセット毎に、最小ステップ数または NA を１行に出力します。

Sample Input

2
1 0 3
4 5 6 7 8
9 0 11
10
0
1 2 3
4 5 6 7 8
9 10 11
0
0
11 10 9
8 7 6 5 4
3 2 1
0
-1

Output for the Sample Input

2
0
NA

Solution in Ruby (judge verdict: Accepted)

### constant

MAX_D = 10
GOAL = ' ABCDEFGHIJK '

NEIGHBORS = [
  [2],
  [2, 5],
  [0, 1, 3, 6],
  [2, 7],
  [5],
  [1, 4, 6, 9],
  [2, 5, 7, 10],
  [3, 6, 8, 11],
  [7],
  [5, 10],
  [6, 9, 11, 12],
  [7, 10],
  [10]
]

### subroutines

def move(s, i, j)
  s0 = s.clone
  s0[i] = s0[j]
  s0[j] = ' '
  s0
end

def neighbors(s)
  nbrs = []

  i0 = s.index(' ')
  for ni in NEIGHBORS[i0]
    nbrs << move(s, i0, ni)
  end

  i1 = s.index(' ', i0 + 1)
  for ni in NEIGHBORS[i1]
    nbrs << move(s, i1, ni)
  end

  nbrs
end

### main

gdists = {}
gdists[GOAL] = 0
queue = [GOAL]

while ! queue.empty?
  v = queue.shift
  next if gdists[v] >= 10

  for nv in neighbors(v)
    if gdists[nv].nil?
      gdists[nv] = gdists[v] + 1
      queue << nv
    end
  end
end

while true
  p1 = gets.strip.to_i
  break if p1 == -1

  ps = [p1]
  4.times.each do
    ps += gets.strip.split(' ').map{|s| s.to_i}
  end

  st = ps.map{|p| (p != 0) ? (p + 64).chr : ' '}.join('')

  queue = [st]
  dists = {}
  dists[st] = 0

  sumd = 'NA'

  while ! queue.empty?
    v = queue.shift
    if ! gdists[v].nil?
      sumd = dists[v] + gdists[v]
      sumd = 'NA' if sumd > 20
      break
    end

    next if dists[v] >= 10

    for nv in neighbors(v)
      if dists[nv].nil?
        dists[nv] = dists[v] + 1
        queue << nv
      end
    end
  end

  puts sumd
end