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

8 Puzzle

The goal of the 8 puzzle problem is to complete pieces on $3 \times 3$ 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 8 as shown below.

1 3 0
4 2 5
7 8 6

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 0

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

Input

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

Output

Print the fewest steps in a line.

Constraints

There is a solution.

Sample Input

1 3 0
4 2 5
7 8 6

Sample Output

4

Solution in Python (judge verdict: Wrong Answer)

#!/usr/bin/python
#coding:utf-8

def _downheap(buff, n):
	size = len(buff)
	while True:
		c = 2 * n + 1
		if c >= size: break
		if c + 1 < size:
			if buff[c] > buff[c + 1]: c += 1
		if buff[n] <= buff[c]: break
		temp = buff[n]
		buff[n] = buff[c]
		buff[c] = temp
		n = c

# ???????????????
def _upheap(buff, n):
	while True:
		p = (n - 1) / 2
		if p < 0 or buff[p] <= buff[n]: break
		temp = buff[n]
		buff[n] = buff[p]
		buff[p] = temp
		n = p

class PQueue:
	def __init__(self, buff = []):
		self.buff = buff[:]   # ?????????
		for n in xrange(len(self.buff) / 2 - 1, -1, -1):
			_downheap(self.buff, n)

	# ??????????????????
	def push(self, data):
		self.buff.append(data)
		_upheap(self.buff, len(self.buff) - 1)

	# ????°???????????????????
	def pop(self):
		if len(self.buff) == 0: raise IndexError
		value = self.buff[0]
		last = self.buff.pop()
		if len(self.buff) > 0:
			# ????????????????§????
			self.buff[0] = last
			_downheap(self.buff, 0)
		return value

	# ????°????????±???????
	def peek(self):
		if len(self.buff) == 0: raise IndexError
		return self.buff[0]

	# ??????
	def isEmpty(self): return len(self.buff) == 0


import time

# ??£??\?????????
adjacent = (
	(1, 3),	   # 0
	(0, 2, 4),	# 1
	(1, 5),	   # 2
	(0, 4, 6),	# 3
	(1, 3, 5, 7), # 4
	(2, 4, 8),	# 5
	(3, 7),	   # 6
	(4, 6, 8),	# 7
	(5, 7)		# 8
)

# ?????°
OPEN = 0
CLOSE = 1
FORE = 0
BACK = 1

# ?????¢??¨?????????
def make_distance_table(board, wide):
	size = len(board)
	table = [[0] * size for _ in xrange(size)]
	for i in xrange(size):
		p = board[i]
		if p == 0: continue
		x1 = i / wide
		y1 = i % wide
		for j in xrange(size):
			x2 = j / wide
			y2 = j % wide
			table[p][j] += max(x1 - x2, x2 - x1)
			table[p][j] += max(y1 - y2, y2 - y1)
	return table

# ?????¢????±???????
def get_distance(board, distance):
	v = 0
	for x in xrange(9):
		p = board[x]
		if p == 0: continue
		v += distance[p][x]
	return v

# ?±???¢?????????
class State:
	def __init__(self, board, space, prev, move, dir, kind = OPEN):
		self.board = board
		self.space = space
		self.prev = prev
		self.move = move
		self.dir = dir
		self.kind = kind
		if dir == FORE:
			dt = start_distance
		else:
			dt = goal_distance
		if prev is None:
			self.cost = move + get_distance(board, dt)
		else:
			p = board[prev.space]
			self.cost = prev.cost + 1 - dt[p][space] + dt[p][prev.space]

	def __cmp__(x, y):
		return x.cost - y.cost

# ???????????? A* ??¢?????´?????????
def a_star_search(start, goal):
	global start_distance, goal_distance
	q = PQueue()
	table ={}
	# ?????????????????????
	start_distance = make_distance_table(goal, 3)
	a = State(start, start.index(0), None, 0, FORE)
	q.push(a)
	table[tuple(start)] = a
	# ??´???????????????
	goal_distance = make_distance_table(start, 3)
	a = State(goal, goal.index(0), None, 0, BACK)
	q.push(a)
	table[tuple(goal)] = a
	while not q.isEmpty():
		a = q.pop()
		if a.kind == CLOSE: continue   # ????£????????????§??????
		for x in adjacent[a.space]:
			b = a.board[:]
			b[a.space] = b[x]
			b[x] = 0
			key = tuple(b)
			if key in table:
				# ???????±???¢?????????
				c = table[key]
				if a.dir != c.dir:
					# ??????
					if a.dir == FORE:
						print print_answer(a)+print_answer_goal(c)-1
					else:
						print print_answer(c)+print_answer_goal(a)-1
					return
				# ?????¢???????????????????????°?????????????????°??????
				if c.move > a.move + 1:
					# ??´??°??????
					if c.kind == OPEN:
						c.kind = CLOSE
						c = State(b, x, a, a.move + 1, a.dir)
						table[key] = c
					else:
						c.prev = a
						c.cost = c.cost - c.move + a.move + 1
						c.move = a.move + 1
						c.kind = OPEN
					# ??????????????????
					q.push(c)
			else:
				c = State(b, x, a, a.move + 1, a.dir)
				q.push(c)
				table[key] = c
		# a ???????????????????±??????????
		a.kind = CLOSE

# ???????????¨???
def print_answer(x):
	if x is not None:
		return 1+print_answer(x.prev)
		#print x.board
	return 0

def print_answer_goal(x):
	r=0
	while x is not None:
		#print x.board
		x = x.prev
		r+=1
	return r

# ??????
goal = [1,2,3,4,5,6,7,8,0]
a = []
try:
	while True:
		a+=[int(e) for e in raw_input().split()]
except EOFError:
	pass

#s = time.clock()
a_star_search(a, goal)
#e = time.clock()
#print "%.3f" % (e - s)