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

#define N 4
#define S 16

typedef struct P{
  int f[S],space,m;
}Puzzle;

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

int MDT[S][S];

int limit;
int path[100];
Puzzle st;

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

int max(int a,int b){
  if(a<b) return b;
  else return a;
}
int min(int a,int b){
  if(a<b) return a;
  else return b;
}
void swap(int *a,int *b){
  int t;
  t=*a;
  *a=*b;
  *b=t;
}

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

  if(st.m==0)return 1;
  if(df+st.m>limit)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(max(p,i)-min(p,i)==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(Puzzle in){
  int i;
  int ans=0;

  in.m=get(in);

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

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

  return 0;
}