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

#define N 4
#define LIM 46


int ans[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},
    y[N*N]={3,0,0,0,
            0,1,1,1,
            1,2,2,2,
            2,3,3,3};

int min = LIM;



void dfs(int p[N][N], int pr[N][N], int n)
{
    int i, j, i0, j0, d = 0;
    int f = 0;
    int tmp[N][N];

    for( i = 0 ; i < N ; i++)
    {
        for( j = 0 ; j < N ; j++)
        {
            if( ans[i][j] != p[i][j]) f++;
            if( p[i][j] == 0)
            {
                i0 = i;
                j0 = j;
            }
            else
                d += abs( j - x[p[i][j]] ) + abs( i-y[p[i][j]] );

        }
    }

    if( f == 0 )
    {
        if( min > n )
        {
            min = n;
        }
        return;
    }
    if( d + n > min ) return;


    if( i0 > 0 && i0 < N )
    {
        memcpy( tmp, p, sizeof(int) * N * N );
        f = tmp[i0][j0];
        tmp[i0][j0] = tmp[i0-1][j0];
        tmp[i0-1][j0] = f;
        if(memcmp( tmp, pr, sizeof(int)*N*N) != 0 )
            dfs(tmp, p, n+1);
    }
    if(j0 > 0 && j0 < N)
    {
        memcpy(tmp, p, sizeof(int) * N * N );
        f = tmp[i0][j0];
        tmp[i0][j0] = tmp[i0][j0-1];
        tmp[i0][j0-1] = f;
        if(memcmp(tmp, pr, sizeof(int) * N * N ) != 0)
            dfs(tmp, p, n+1);
    }

    if( i0 >= 0 && i0 < N-1)
    {
        memcpy( tmp, p, sizeof(int) * N * N);
        f = tmp[i0][j0];
        tmp[i0][j0] = tmp[i0+1][j0];
        tmp[i0+1][j0] = f;
        if(memcmp(tmp, pr, sizeof(int) * N * N ) != 0 )
            dfs(tmp, p, n+1);
    }
    if( j0 >= 0 && j0 < N-1)
    {
        memcpy( tmp, p, sizeof(int) * N * N );
        f = tmp[i0][j0];
        tmp[i0][j0] = tmp[i0][j0+1];
        tmp[i0][j0+1] = f;
        if(memcmp( tmp, pr, sizeof(int) * N * N ) != 0)
            dfs( tmp, p, n+1 );
    }

}

int main()
{
    int i,j;
    int A[N][N];

    for( i = 0 ; i < N ; i++)
    {
        for( j = 0 ; j < N ; j++)
        {
            scanf("%d", &A[i][j]);
        }
    }
    dfs( A, A, 0);

    printf("%d\n", min);

    return 0;
}