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: Accepted)

#include<stdio.h>

#define SIZE 9
#define MAX 362880
#define TRUE 1
#define GOAL 2

/*8パズルの繋りを示す隣接リスト*/
int puzzle[SIZE][5]={
  1,3,-1,-1,-1,  0,4,2,-1,-1,  1,5,-1,-1,-1,
  0,4,6,-1,-1,   1,3,5,7,-1,   2,4,8,-1,-1,
  3,7,-1,-1,-1,  4,6,8,-1,-1,  5,7,-1,-1,-1
};

int board[MAX][SIZE];  /*局面*/
int Space[MAX];        /*スペースの位置*/
int prev_board[MAX];
int check_table[MAX];
int init_board[SIZE];
int goal_board[SIZE]={1,2,3,4,5,6,7,8,0};

int change_num(int *);  /*局面を番号に変換*/
void Search(void);
void print_answer(int);

int main(){
  int i;

  for(i=0;i<SIZE;i++) scanf("%d",&init_board[i]);

  Search();

  return 0;

}
  

int change_num(int *board){
  int work[SIZE];
  int i,j,k,value=0;
  int fact_table[SIZE]={40320,5040,720,120,24,6,2,1,0};

  for(i=0;i<SIZE;i++) work[i]=board[i];

  for(i=0;i<SIZE-1;i++){
    value+=fact_table[i]*work[i];
    for(j=i+1;j<SIZE;j++){
      if(work[i]<work[j]) work[j]-=1;
    }
  }
  return value;
}

void Search(void){
  int i,j,k,n,s,front=0,rear=1,count=0,init,goal;

  for(i=0;i<SIZE;i++){
    board[0][i]=init_board[i];
    if(init_board[i]==0) Space[0]=i;
  }
  prev_board[0]=-1;
  init=change_num(init_board);
  goal=change_num(goal_board);
  check_table[init]=TRUE;
  check_table[goal]=GOAL;

  if(init==goal) {
      print_answer(0);
      return;
  }
  
  while(front<rear){
    s=Space[front];
    for(i=0;(n=puzzle[s][i])!=-1;i++){
      /*状態のコピー*/
      for(j=0;j<SIZE;j++) board[rear][j]=board[front][j];
      board[rear][s]=board[rear][n]; /*空白に移動*/
      board[rear][n]=0;
      Space[rear]=n;
      prev_board[rear]=front;
      k=change_num(board[rear]);
      if(check_table[k]==GOAL){
	/*発見*/
	print_answer(rear);
	return;
      }
      
      else if(!check_table[k]){
	  /*キューに登録*/
	  check_table[k]=TRUE;
	  rear++;
	}
    }
    front++;
  }
}
	
void print_answer(int n){
  int i,j,count=0;

  while(n!=0){
    count++;
    n=prev_board[n];
  }

  printf("%d\n",count);

  /* if(n!=0) print_answer(prev_board[n]); */

  /* for(i=0;i<3;i++){ */
  /*   for(j=0;j<3;j++){ */
  /*     printf("%d ",board[n][i*3+j]); */
  /*   } */
  /*   printf("\n"); */
  /* } */
  /* printf("\n"); */
}