Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

15 Puzzle

The goal of the 15 puzzle problem is to complete pieces on $4 \times 4$ 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 15 as shown below.

1 2 3 4
6 7 8 0
5 10 11 12
9 13 14 15

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
9 10 11 12
13 14 15 0

Write a program which reads an initial state of the puzzle and prints the fewest steps to solve the puzzle.

Input

The $4 \times 4$ integers denoting the pieces or space are given.

Output

Print the fewest steps in a line.

Constraints

The given puzzle is solvable in at most 45 steps.

Sample Input

1 2 3 4
6 7 8 0
5 10 11 12
9 13 14 15

Sample Output

8

Solution in C (judge verdict: Accepted)

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 4
#define U 16
#define LIM 100


int dx[4]={0,-1,0,1},dy[4]={1,0,-1,0};
char dir[4]={'r','u','l','d'};
int m[U][U];


typedef struct {
  int a[U],s,md;
}P;

P st;
int lim,p[LIM];

int get(P);
int solved();
int dfs(int,int);
int intedeep(P);
int max(int,int);
int min(int,int);
void swap(int *,int *);

int main(){
  int i,j;
  P in;
 

  for(i=0;i<U;i++){
    for(j=0;j<U;j++){
      m[i][j]=abs(i/N - j/N) + abs(i%N - j%N);
    }
  }
  for(i=0;i<U;i++){
    scanf("%d",&in.a[i]);
    
    if(in.a[i]==0){
      in.a[i]=U;
      in.s = i;
    }
  }
  
  printf("%d\n",intedeep(in));

  return 0;
}

int get(P x){
  int sm=0,i;

  for(i=0;i<U;i++){
    if(x.a[i]==U) continue;

    sm+=m[i][x.a[i]-1];
		  
  }
  return sm;
}

int solved(){
  int i;

  for(i=0;i<U;i++)
    if(st.a[i] != i+1) return 0;
  return 1;

}

int intedeep(P in){
  int i,a;

  in.md = get(in);
  for(lim=in.md;lim<=LIM;lim++){
    st=in;
    if(dfs(0,-LIM)){
      a=0;
      for(i=0;i<lim;i++){
	a++;
      }return a;
    
    
    }
  }
  return -1;
}

int dfs(int dep,int pre){
  int x1,y1,x2,y2,i;
  x1= st.s/N;
  y1= st.s%N;
  P temp;
  if(st.md == 0) return 1;
  if(dep + st.md>lim) return 0;
  for(i=0;i<4;i++){
    x2 = x1 + dx[i];
    y2 = y1 + dy[i];
    if(x2<0||x2>=N||y2<0||y2>=N) continue;
    if(max(pre,i)-min(pre,i)==2) continue;
    temp = st;
    st.md-=m[x2*N +y2][st.a[x2*N +y2]-1];
    st.md+=m[x1*N +y1][st.a[x2*N +y2]-1];
    swap(&st.a[x2*N+y2],&st.a[x1*N+y1]);
    st.s=x2*N+y2;
    if(dfs(dep+1,i)){
      p[dep] = i;
      return 1;
    }
    st=temp;
  }
  return 0;
}

int max(int pre,int i){
  if(pre>i) return pre;
  else return i;
}

int min(int pre,int i){
  if(pre<i) return pre;
  else return i;
}

void  swap(int *x,int *y){

  int temp;

  temp = *x;
  *x = *y;
  *y = temp;

}