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 M 16
#define N 4
#define yes 1
#define no -1
#define lim 100

typedef struct{
  int a[M],b,c;
}Puzzle;

Puzzle now;

int s1[4]={0,-1,0,1};
int s2[4]={1,0,-1,0};
char contl[4]={'r','u','l','d'};
int bord[M][M];

int max,leng[lim];

int in_bord(Puzzle x){
  int i,count=0;
  for(i=0;i<M;i++){
    if(x.a[i]==M) continue;
    count+=bord[i][x.a[i]-1];
  }
  return count;
}

int dfs(int deep,int z){
  int i,r1,r2,y1,y2,change;
  
  if(now.c==0) return yes;
  if(deep+now.c>max) return no;

   r1=now.b/N;
   r2=now.b%N;
  Puzzle comp;

  for(i=0;i<4;i++){
    y1=r1+s1[i];
    y2=r2+s2[i];

    if(y1<0 || y2<0 || y1>=N || y2>=N) continue;
    if(abs(z-i)==2) continue;
    comp=now;

    now.c-=bord[y1*N+y2][now.a[y1*N+y2]-1];
    now.c+=bord[r1*N+r2][now.a[y1*N+y2]-1];
    change=now.a[y1*N+y2];
    now.a[y1*N+y2]=now.a[r1*N+r2];
    now.a[r1*N+r2]=change;
    now.b=y1*N+y2;
    if(dfs(deep+1,i)==yes){
      leng[deep]=i;
      return yes;
    }
    now=comp;
  }
  return no;
}

void solve(Puzzle x){
  int i,count=0;
  
  x.c=in_bord(x);
  for(max=x.c;max<=lim;max++){
    now=x;
    if(dfs(0,-100)==yes){
      for(i=0;i<max;i++){
	count++;
      }
      printf("%d\n",count);
      return;
    }
  }
}
      

int main(){
  int i,j,keep;
  Puzzle in;

  for(i=0;i<M;i++){
    for(j=0;j<M;j++){
      bord[i][j]=abs(i/N-j/N)+abs(i%N-j%N);
    }
  }

  for(i=0;i<M;i++){
    scanf("%d",&in.a[i]);
    if(in.a[i]==0) keep=i;
  }
      in.a[keep]=M;
      in.b=keep;

  solve(in);

  return 0;
}