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: Memory Limit Exceeded)

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

namespace ConsoleApplication1
{
    struct Puzzle
    {
        internal int[] f;
        internal int space;
        internal string path;

        public Puzzle(int n)
        {
            f = new int[n];
            space = default(int);
            path = default(string);
        }

        public Puzzle(Puzzle other)
        {
            int len = other.f.Length;
            f = new int[len];
            other.f.CopyTo(f, 0);

            space = other.space;
            path = other.path;
        }
    }

    class NPuzzle
    {
        readonly int n, h, w;

        readonly int[] moveX = new int[] { 0, -1, 0, +1 };
        readonly int[] moveY = new int[] { -1, 0, +1, 0 };
        readonly char[] dir = new char[] { 'u', 'l', 'd', 'r' };

        public NPuzzle(int h, int w)
        {
            this.h = h;
            this.w = w;
            n = h * w;
        }

        public string Solve(Puzzle s)
        {
            Queue<Puzzle> que = new Queue<Puzzle>();
            HashSet<Puzzle> visited = new HashSet<Puzzle>();

            que.Enqueue(s);
            visited.Add(s);

            while (que.Count > 0)
            {
                Puzzle u = que.Dequeue();

                if (IsTarget(u)) return u.path;

                int sx = u.space % w;
                int sy = u.space / w;

                for (int r = 0; r < 4; r++)
                {
                    int tx = sx + moveX[r];
                    int ty = sy + moveY[r];

                    if (!IsValid(tx, ty)) continue;

                    Puzzle v = new Puzzle(u);

                    int temp = v.f[u.space];
                    v.f[u.space] = v.f[tx + ty * w];
                    v.f[tx + ty * w] = temp;

                    v.space = tx + ty * w;

                    if (!visited.Contains(v))
                    {
                        visited.Add(v);
                        v.path += dir[r];
                        que.Enqueue(v);
                    }
                }
            }
            return null;
        }

        private bool IsValid(int x, int y)
        {
            if (x < 0) return false;
            if (y < 0) return false;
            if (x >= w) return false;
            if (y >= h) return false;
            return true;
        }

        private bool IsTarget(Puzzle p)
        {
            for (int i = 0; i < n; i++)
            {
                if (p.f[i] != i + 1) return false;
            }
            return true;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            int h = 3, w = 3;
            int n = h * w;

            NPuzzle NP = new NPuzzle(h, w);
            Puzzle s = new Puzzle(n);

            for (int i = 0; i < h; i++)
            {
                int[] input = Array.ConvertAll(Console.ReadLine().Split(' '), int.Parse);

                for (int j = 0; j < w; j++)
                {
                    int index = i * w + j;
                    s.f[index] = input[j];

                    if (input[j] == 0)
                    {
                        s.f[index] = n;
                        s.space = index;
                    }
                }
            }

            string ans = NP.Solve(s);

            Console.WriteLine(ans.Length);
        }
    }
}