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>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

char *flag;
int head,rear;
int *que;
int factorial[10];

int cal_factorial(int n) {
  if(n == 0) return 1;
  return cal_factorial(n-1)*n;
}

int stotag(char *s) {
  int tag = 0;
  int i;
  for(i = 0; i < 9; i++) {
    int t,j;
    t = 0;
    for(j = 0; j < i; j++) {
      if(s[j] < s[i]) t++;
    }
    tag += factorial[8-i]*(s[i]-'0'-t);
  }
  return tag;
}

char *tagtos(int tag) {
  int i;
  char *s;
  s = (char*)malloc(sizeof(char)*10);
  for(i = 0; i < 9; i++) {
    s[i] = tag%factorial[9-i]/factorial[8-i] + '0';
  }
  s[9] = '\0';
  for(i = 7; i >= 0; i--) {
    int j;
    for(j = 8; j > i; j--) {
      if(s[i] <= s[j]) s[j]++;
    }
  }
  
  return s;
}


char *move_up(char s[], int x) {
  if(x < 3) return NULL;
  char *s_new;
  s_new = (char*)malloc(sizeof(char)*10);
  strcpy(s_new,s);
  s_new[x] = s[x-3];
  s_new[x-3] = s[x];
  return s_new;
}

char *move_left(char s[], int x) {
  if(x%3 == 0) return NULL;
  char *s_new;
  s_new = (char*)malloc(sizeof(char)*10);
  strcpy(s_new,s);
  s_new[x] = s[x-1];
  s_new[x-1] = s[x];
  return s_new;
}

char *move_right(char s[], int x) {
  if(x%3 == 2) return NULL;
  char *s_new;
  s_new = (char*)malloc(sizeof(char)*10);
  strcpy(s_new,s);
  s_new[x] = s[x+1];
  s_new[x+1] = s[x];
  return s_new;
}

char *move_down(char s[], int x) {
  if(x > 5) return NULL;
  char *s_new;
  s_new = (char*)malloc(sizeof(char)*10);
  strcpy(s_new,s);
  s_new[x] = s[x+3];
  s_new[x+3] = s[x];
  return s_new;
}

int create(char s[], int t) {
  if(strcmp(s,"123456780") == 0) return t;
  int tag = stotag(s);
  if(flag[tag]) return 0;
  flag[tag] = t;
  que[rear] = tag;
  rear++;
  return 0;
}

int distance(char *s_new) {
  char s[] = "123456780";
  int i;
  int sum = 0;
  for(i = 0; i < 9; i++) {
    int a = 0;
    int b = 0;
    while(s[a]-'0' != i) a++;
    while(s_new[b]-'0' != i) b++;
    sum += abs(a/3-b/3) + abs(a%3-b%3);
  }
  return sum;
}

int check_x(char *s) {
  int i = 0;
  while(s[i] != '0') i++;
  return i;
}

int cal() {
  char *s_right,*s_left,*s_up,*s_down;
  int right,left,up,down,min;
  int k,tag;

  tag = que[head];
  char *s = tagtos(tag);
  int x = check_x(s);
  
  if((s_right = move_right(s, x)) != NULL) {
    right = distance(s_right);
    if((k = create(s_right,flag[tag]+1))) return k;
  }else{
    right = INT_MAX;
  }
  if((s_left = move_left(s, x)) != NULL) {
    left = distance(s_left);
     if((k = create(s_left,flag[tag]+1))) return k;
  }else{
    left = INT_MAX;
  }
  if ((s_up = move_up(s, x)) != NULL) {
    up = distance(s_up);
    if((k = create(s_up,flag[tag]+1))) return k;
  }else{
    up = INT_MAX;
  }
  if((s_down = move_down(s, x)) != NULL) {
    down = distance(s_down);
    if((k = create(s_down,flag[tag]+1))) return k;
  }else{
    down = INT_MAX;
  }
  /*
  min = right;
  if(min > left) min = left;  
  if(min > up) min = up;  
  if(min > down) min = down;

  if(right == min) {
    if((k = create(s_right,flag[tag]+1))) return k;
  }
  if(left == min) {
    if((k = create(s_left,flag[tag]+1))) return k;
  }
  if(up == min) {
    if((k = create(s_up,flag[tag]+1))) return k;
  }
  if(down == min) {
    if((k = create(s_down,flag[tag]+1))) return k;
  }
  */

  free(s);
  if(s_right != NULL) free(s_right);
  if(s_left != NULL) free(s_left);
  if(s_up != NULL) free(s_up);
  if(s_down != NULL) free(s_down);
  head++;
  return 0;
}
  

int solve(char s0[]) {
  int k;
  if((k = create(s0,1))) return k;
  
  while(!(k = cal())) {
    if(head == rear) break;
  }
  return k;
}

int main()
{
  int i,d;
  char s[10];
  for(i = 0; i < 10; i++) factorial[i] = cal_factorial(i);
  flag = (char*)malloc(sizeof(char)*factorial[9]);
  memset(flag , 0, factorial[9]);
  que = (int*)malloc(sizeof(int)*factorial[9]);
  head = 0;
  rear = 0;
  for (i = 0; i < 9; i++) {
    scanf("%d", &d);
    s[i] = d+'0';
  }
  s[9] = '\0';
  printf("%d\n",solve(s)-1);
  
  return 0;
}