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 x[N*N]={3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2};
int y[N*N]={3,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3};
int heuristic[N*N][N*N];
int curMinCost=46;
void searchMinCost(int[N][N],int,int);
int main(void)
{
  int i,j;
  int tempArr[N][N];
  for(i=0;i<N*N;i++)
    {
      for(j=0;j<N*N;j++)
        {
          heuristic[i][j]=abs(y[i]-y[j])+abs(x[i]-x[j]);
        }
    }
  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=0;
  int i,j;
  int blankI,blankJ;
  int index;
  for(i=0;i<N;++i)
    {
      for(j=0;j<N;++j)
        {
          if(tempArr[i][j]!=ansArr[i][j])
            {
              h+=heuristic[tempArr[i][j]][ansArr[i][j]];
            }
          if(tempArr[i][j]==0)
            {
              blankI=i;
              blankJ=j;
            }
        }
    }
  if(h==0)
    {
      if(curCost<curMinCost) curMinCost=curCost;
      return;
    }
  h=h*7/9;//I don't know why it works well
  if(curCost+h>curMinCost) return;
  if(blankI>0&&lastMove!=3)
    {
      index=blankI-1;
      tempArr[blankI][blankJ]=tempArr[index][blankJ];
      tempArr[index][blankJ]=0;
      searchMinCost(tempArr,1,curCost+1);
      tempArr[index][blankJ]=tempArr[blankI][blankJ];
      tempArr[blankI][blankJ]=0;
    }
  if(blankJ>0&&lastMove!=4)
    {
      index=blankJ-1;
      tempArr[blankI][blankJ]=tempArr[blankI][index];
      tempArr[blankI][index]=0;
      searchMinCost(tempArr,2,curCost+1);
      tempArr[blankI][index]=tempArr[blankI][blankJ];
      tempArr[blankI][blankJ]=0;
    }
  if(blankI<N-1&&lastMove!=1)
    {
      index=blankI+1;
      tempArr[blankI][blankJ]=tempArr[index][blankJ];
      tempArr[index][blankJ]=0;
      searchMinCost(tempArr,3,curCost+1);
      tempArr[index][blankJ]=tempArr[blankI][blankJ];
      tempArr[blankI][blankJ]=0;
    }
  if(blankJ<N-1&&lastMove!=2)
    {
      index=blankJ+1;
      tempArr[blankI][blankJ]=tempArr[blankI][index];
      tempArr[blankI][index]=0;
      searchMinCost(tempArr,4,curCost+1);
      tempArr[blankI][index]=tempArr[blankI][blankJ];
      tempArr[blankI][blankJ]=0;
    }
}