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 C# (judge verdict: Time Limit Exceeded)

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

namespace ALDS1_13_B_8_Puzzle
{
	class Program
	{
		static void Main ( string[] args )
		{
			//input
			List<int> input = new List<int> (9);

			for (int lp = 0; lp < 3; lp++)
			{
				int[] state = Array.ConvertAll (Console.ReadLine ().Split (' '), int.Parse);
				input.AddRange (state);
			}

			//process
			Queue<Puzzle> puzzleQueue = new Queue<Puzzle> (1000);
			Equal equal = new Equal ();
			HashSet<int[]> puzzleState = new HashSet<int[]> (equal);

			int[] answer = { 1, 2, 3, 4, 5, 6, 7, 8, 0 };

			Puzzle p = new Puzzle (input.ToArray (), 0, input.IndexOf (0));
			puzzleQueue.Enqueue (p);
			puzzleState.Add (p.Area);

			while (puzzleQueue.Count != 0)
			{
				Puzzle item = puzzleQueue.Dequeue ();

				if (Puzzle.IsMatch (item.Area, answer))
				{
					Console.WriteLine (item.Count);
					break;
				}

				Puzzle[] next = item.Move ();

				foreach (var element in next)
				{
					if (puzzleState.Add (element.Area))
					{
						puzzleQueue.Enqueue (element);
					}
				}
			}

		}
	}

	class Puzzle
	{
		public Puzzle ( int[] area, int count, int emptyIndex )
		{
			this.Area = new int[Length];
			area.CopyTo (this.Area, 0);
			this.Count = count;
			this.EmptyIndex = emptyIndex;
		}

		public int[] Area { private set; get; }
		public int Count { private set; get; }
		private int EmptyIndex { set; get; }

		private const int Length = 9;

		public Puzzle[] Move ()
		{
			int[] indexArray;
			int createCount = MoveData (EmptyIndex, out indexArray);

			Puzzle[] puzzle = new Puzzle[createCount];

			for (int lp = 0; lp < puzzle.Length; lp++)
			{
				int index = indexArray[lp];

				int[] copyArea = new int[Length];
				Area.CopyTo (copyArea, 0);

				var tmp = copyArea[EmptyIndex];
				copyArea[EmptyIndex] = copyArea[index];
				copyArea[index] = tmp;

				puzzle[lp] = new Puzzle (copyArea, Count + 1, index);
			}

			return puzzle;
		}

		public static bool IsMatch ( int[] area1, int[] area2 )
		{
			if (area1.SequenceEqual (area2))
				return true;
			else
				return false;
		}

		private int MoveData ( int emptyIndex, out int[] indexArray )
		{
			int createCount = 0;
			indexArray = null;

			switch (emptyIndex)
			{
				case 0:
					createCount = 2;
					indexArray = new int[createCount];
					indexArray[0] = 1;
					indexArray[1] = 3;
					break;
				case 1:
					createCount = 3;
					indexArray = new int[createCount];
					indexArray[0] = 0;
					indexArray[1] = 2;
					indexArray[2] = 4;
					break;
				case 2:
					createCount = 2;
					indexArray = new int[createCount];
					indexArray[0] = 1;
					indexArray[1] = 5;
					break;
				case 3:
					createCount = 3;
					indexArray = new int[createCount];
					indexArray[0] = 0;
					indexArray[1] = 4;
					indexArray[2] = 6;
					break;
				case 4:
					createCount = 4;
					indexArray = new int[createCount];
					indexArray[0] = 1;
					indexArray[1] = 3;
					indexArray[2] = 5;
					indexArray[3] = 7;
					break;
				case 5:
					createCount = 3;
					indexArray = new int[createCount];
					indexArray[0] = 2;
					indexArray[1] = 4;
					indexArray[2] = 8;
					break;
				case 6:
					createCount = 2;
					indexArray = new int[createCount];
					indexArray[0] = 3;
					indexArray[1] = 7;
					break;
				case 7:
					createCount = 3;
					indexArray = new int[createCount];
					indexArray[0] = 4;
					indexArray[1] = 6;
					indexArray[2] = 8;
					break;
				case 8:
					createCount = 2;
					indexArray = new int[createCount];
					indexArray[0] = 5;
					indexArray[1] = 7;
					break;
			}

			return createCount;
		}
	}

	class Equal : EqualityComparer<int[]>
	{
		public override bool Equals ( int[] area1, int[] area2 )
		{
			return area1.SequenceEqual (area2);
		}
		public override int GetHashCode ( int[] item )
		{
			return base.GetHashCode ();
		}
	}
}