Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

15 Puzzle

The goal of the 15 puzzle problem is to complete pieces on $4 \times 4$ cells where one of the cells is empty space.

In this problem, the space is represented by 0 and pieces are represented by integers from 1 to 15 as shown below.

1 2 3 4
6 7 8 0
5 10 11 12
9 13 14 15

You can move a piece toward the empty space at one step. Your goal is to make the pieces the following configuration in the shortest move (fewest steps).

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 0

Write a program which reads an initial state of the puzzle and prints the fewest steps to solve the puzzle.

Input

The $4 \times 4$ integers denoting the pieces or space are given.

Output

Print the fewest steps in a line.

Constraints

The given puzzle is solvable in at most 45 steps.

Sample Input

1 2 3 4
6 7 8 0
5 10 11 12
9 13 14 15

Sample Output

8

Solution in Ruby (judge verdict: Time Limit Exceeded)

require 'set'

Move = [ [1, 4], [0, 2, 5], [1, 3, 6], [2, 7],
         [0, 5, 8], [1, 4, 6, 9], [2, 5, 7, 10], [3, 6, 11],
         [4, 9, 12], [5, 8, 10, 13], [6, 9, 11, 14], [7, 10, 15],
         [8, 13], [9, 12, 14], [10, 13, 15], [11, 14]
        ]

R = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
C = [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]

def min_heapify(x = 1)
  l = 2*x
  r = 2*x+1
  if l <= $n && $heap[l][0] < $heap[x][0]
    minimum = l
  else
    minimum = x
  end
  if r <= $n && $heap[r][0] < $heap[minimum][0]
    minimum = r
  end
  if minimum != x
    $heap[x], $heap[minimum] = $heap[minimum], $heap[x]
    min_heapify(minimum)
  end
end

def extract
  key = $heap[1]
  $heap[1] = $heap[$n]
  $n -= 1
  min_heapify
  key
end

def insert(key)
  $n += 1
  $heap[$n] = key
  i = $n
  while i > 1 && $heap[i/2][0] > $heap[i][0]
    $heap[i], $heap[i/2] = $heap[i/2], $heap[i]
    i /= 2
  end
end

def judge(brd, c)
  ret = c
  16.times do |i|
    if brd[i] > 0
      [R, C].each do |a|
        ret += (a[i] - a[brd[i] - 1]).abs
      end
    end
  end
  ret
end

brd = 4.times.map{ gets.split.map(&:to_i) }.flatten
$heap = []
$n = 0
insert [judge(brd, 0), brd, 0]
set = Set.new([])
set.add(brd)
while $n > 0
  val, b, cnt = extract
  next if val > 45
  if val == cnt
    p cnt
    break
  end
  n = b.index(0)
  Move[n].each do |m|
    b[n], b[m] = b[m], b[n]
    nb = b.dup
    unless set.include?(nb)
      set.add(nb)
      insert [judge(b, cnt+1), nb, cnt + 1]
    end
    b[n], b[m] = b[m], b[n]
  end
end