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 N2 16
#define LIMIT 80

typedef struct {
  int b[N2+1];
} Board;
Board board;
int minstep;
typedef enum { R, U, L, D } Direction;
typedef struct { int pos; Direction dir; } Motion;

//  0  1  2  3
//  4  5  6  7
//  8  9 10 11
// 12 13 14 15
 
const Motion motion[N2][5] =
  {{{1,L},{4,U},{-1}}, {{0,R},{2,L},{5,U},{-1}}, {{1,R},{3,L},{6,U},{-1}},{{2,R},{7,U},{-1}},
   {{0,D},{5,L},{8,U},{-1}}, {{1,D},{6,L},{9,U},{4,R},{-1}},  {{2,D},{7,L},{10,U},{5,R},{-1}}, {{3,D},{11,U},{6,R},{-1}},
   {{4,D},{9,L},{12,U},{-1}}, {{5,D},{10,L},{13,U},{8,R},{-1}},  {{6,D},{11,L},{14,U},{9,R},{-1}}, {{7,D},{15,U},{10,R},{-1}},
   {{8,D},{13,L},{-1}}, {{9,D},{14,L},{12,R},{-1}}, {{10,D},{15,L},{13,R},{-1}},{{11,D},{14,R},{-1}}};

const int rr[4][5] = {{0,0,1,0,0},{0,0,0,1,0},{1,0,0,0,0},{0,1,0,0,0}};

int dd[N2][N2];
int dist(int *b)
{
  int i, n, d = 0;
  for (i=0; i<N2; i++) {
    n = b[i]-1;
    if (n<0) {
      continue;
    }
    d += dd[n][i];
  }
  return d;
}

void search(int step, Motion prev)
{
  int i, d=0;
  d = dist(board.b);
  if (step+d>minstep) return;
  if (d==0) {
    printf("%d\n", step);
    exit(0);
  }
  Board board_bak = board;
  for (i=0; motion[prev.pos][i].pos>=0; i++) {
    Motion m = motion[prev.pos][i];
    if (rr[m.dir][prev.dir]) continue; //元に戻るのを防止
    board.b[prev.pos] = board.b[m.pos];
    board.b[m.pos] = 0;
    search(step+1, m);
    board = board_bak;
  }
}

int main()
{
  int i, j;
  for (i=0; i<N2; i++)
    for (j=0; j<N2; j++)
      dd[i][j] = abs(i%N-j%N) + abs(i/N-j/N);
  
  Board ini_board;
  fscanf(stdin, "%d %d %d %d\n", &ini_board.b[0],&ini_board.b[1],&ini_board.b[2],&ini_board.b[3]);
  fscanf(stdin, "%d %d %d %d\n", &ini_board.b[4],&ini_board.b[5],&ini_board.b[6],&ini_board.b[7]);
  fscanf(stdin, "%d %d %d %d\n", &ini_board.b[8],&ini_board.b[9],&ini_board.b[10],&ini_board.b[11]);
  fscanf(stdin, "%d %d %d %d\n", &ini_board.b[12],&ini_board.b[13],&ini_board.b[14],&ini_board.b[15]);
  
  ini_board.b[N2]=0;

  Motion m;
  m.dir = 4;
  for (i=0; i<N2; i++)
    if (ini_board.b[i]==0) {
      m.pos = i;
      break;
    }

  for (minstep=dist(ini_board.b); minstep<=LIMIT; minstep++) {
    board = ini_board;
    search(0, m);
  }
  puts("no result.");
  return 0;
}