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<stdlib.h>

#define N 4
#define N2 16

typedef struct{
  int f[N2];
  int space;
  int m;
}Puz;

int dx[4]={0,-1,0,1};
int dy[4]={1,0,-1,0};

int MDT[N2][N2];

int lim;
int path[100];
Puz st;

int getAllMD(Puz Z){
  int i,sum=0;
  for(i=0;i<N2;i++){
    if(Z.f[i] == N2) continue;
    sum+=MDT[i][Z.f[i]-1];
  }
  return sum;
}

void swap(int *a,int *b){
  int tmp;
  tmp=*a;
  *a=*b;
  *b=tmp;
}

char dfs(int df,int p){
  int sx,sy,tx,ty,i,max,min;
  Puz tmp;

  if(st.m==0)return 1;
  if(df+st.m>lim)return 0;

  sx=st.space/N;
  sy=st.space%N;

  for(i=0;i<4;i++){
    tx=sx+dx[i];
    ty=sy+dy[i];

    if(tx<0||tx>=N||ty<0||ty>=N) continue;

    if(p>i){max=p;min=i;}
    else {max=i;min=p;}
    
    if(max-min==2)continue;
    tmp=st;

    st.m-=MDT[tx*N+ty][st.f[tx*N+ty]-1];
    st.m+=MDT[sx*N+sy][st.f[tx*N+ty]-1];

    //printf("st.m=%d\n",st.m);

    swap(&st.f[tx*N+ty],&st.f[sx*N+sy]);

    st.space=tx*N+ty;
    if(dfs(df+1,i)){
      path[df]=i;
      return 1;
    }
    st=tmp;
  }
  return 0;
}

int id(Puz in){
  int i;
  int ans=0;

  in.m=getAllMD(in);

  for(lim=in.m;lim<=100;lim++){
      //  printf("aaa\n");
    st=in;
    if(dfs(0,-100)){
      ans=0;;
      for(i=0;i<lim;i++) ans++;
      return ans;
    }
  }
  return -1;
}

int main(){
  int i,j;
  Puz in; 
  for(i=0;i<N2;i++)
    for(j=0;j<N2;j++)
      MDT[i][j]=abs(i/N-j/N)+abs(i%N-j%N);
  
  for(i=0;i<N2;i++){
    //printf("aaa\n");
    scanf("%d",&in.f[i]);
    if(in.f[i]==0){
      in.f[i]=N2;
      in.space=i;
    }
  }
  
  printf("%d\n",id(in));

  return 0;
}