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> (3000);
			Equal equal = new Equal ();
			Dictionary<int[], bool> puzzleState = new Dictionary<int[], bool> (3000, 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, true);

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

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

				Puzzle[] next = item.Move (puzzleState);

				foreach (var element in next)
				{
					puzzleState.Add (element.Area, true);
					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 ( Dictionary<int[], bool> dictionary )
		{
			int[] indexArray;
			int createCount = MoveData (EmptyIndex, out indexArray);

			List<Puzzle> puzzle = new List<Puzzle> (createCount);

			for (int lp = 0; lp < createCount; 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;

				if (!dictionary.ContainsKey (copyArea))
				{
					puzzle.Add (new Puzzle (copyArea, Count + 1, index));
				}
			}

			return puzzle.ToArray ();
		}

		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;

			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;
				default:
					createCount = -1;
					indexArray = null;
					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 ();
			return item[0] + item[1] * 10 + item[2] * 100 + item[3] * 1000;
		}
	}
}