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: Time Limit Exceeded)

#include<stdio.h>
#include<stdlib.h>
#define N 4
int ansArr[N][N]={{ 1, 2, 3, 4},
		  { 5, 6, 7, 8},
		  { 9,10,11,12},
		  {13,14,15, 0}};
int curMinCost=46;
void searchMinCost(int[N][N],int,int);
int heuristic(int[N][N]);
int getBlankI(int[N][N]);
int getBlankJ(int[N][N]);
int main(void)
{
  int i,j;
  int tempArr[N][N];
  for(i=0;i<N;i++)
    for(j=0;j<N;j++)
      scanf("%d",&tempArr[i][j]);
  searchMinCost(tempArr,0,0);
  printf("%d\n",curMinCost);
  return 0;
}
void searchMinCost(int tempArr[N][N],int lastMove,int curCost)
{
  int h=heuristic(tempArr);
  int blankI,blankJ;
  if(h==-1&&curCost<curMinCost)
    {
      curMinCost=curCost;
      return;
    }
  if(curCost+h>curMinCost) return;
  blankI=getBlankI(tempArr);
  blankJ=getBlankJ(tempArr);
  if(blankI>0&&lastMove!=3)
    {
      tempArr[blankI][blankJ]=tempArr[blankI-1][blankJ];
      tempArr[blankI-1][blankJ]=0;
      searchMinCost(tempArr,1,curCost+1);
      tempArr[blankI-1][blankJ]=tempArr[blankI][blankJ];
      tempArr[blankI][blankJ]=0;
    }
  if(blankJ>0&&lastMove!=4)
    {
      tempArr[blankI][blankJ]=tempArr[blankI][blankJ-1];
      tempArr[blankI][blankJ-1]=0;
      searchMinCost(tempArr,2,curCost+1);
      tempArr[blankI][blankJ-1]=tempArr[blankI][blankJ];
      tempArr[blankI][blankJ]=0;
    }
  if(blankI<N-1&&lastMove!=1)
    {
      tempArr[blankI][blankJ]=tempArr[blankI+1][blankJ];
      tempArr[blankI+1][blankJ]=0;
      searchMinCost(tempArr,3,curCost+1);
      tempArr[blankI+1][blankJ]=tempArr[blankI][blankJ];
      tempArr[blankI][blankJ]=0;
    }
  if(blankJ<N-1&&lastMove!=2)
    {
      tempArr[blankI][blankJ]=tempArr[blankI][blankJ+1];
      tempArr[blankI][blankJ+1]=0;
      searchMinCost(tempArr,4,curCost+1);
      tempArr[blankI][blankJ+1]=tempArr[blankI][blankJ];
      tempArr[blankI][blankJ]=0;
    } 
}
int heuristic(int tempArr[N][N])
{
  int i,j;
  int ret=0;
  for(i=0;i<N;i++)
    {
      for(j=0;j<N;j++)
	{
	  if(tempArr[i][j]!=ansArr[i][j])
	    {
	      ret+=abs(((tempArr[i][j]+N*N-1)%N)/4-i);
	      ret+=abs(((tempArr[i][j]+N*N-1)%N)%4-j);
	    }
	}
    }
  if(ret==0) return -1;
  return ret*2/5;
}
int getBlankI(int tempArr[N][N])
{
  int i,j;
  for(i=0;i<N;i++)
    {
      for(j=0;j<N;j++)
	{
	  if(tempArr[i][j]==0) return i;
	}
    }
  return -1;
}
int getBlankJ(int tempArr[N][N])
{
  int i,j;
  for(i=0;i<N;i++)
    {
      for(j=0;j<N;j++)
	{
	  if(tempArr[i][j]==0) return j;
	}
    }
  return -1;
}