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 N 4

int map[N][N];
int cpy[N][N];
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};

int dfs(int x, int y, int point, int depth, int limit);
int result();

int main() {
    int i, j;
  
    for(i = 0; i < N; i++) {
        for(j = 0; j < N; j++) {
            scanf("%d", &map[i][j]);
        }
    }
    printf("%d\n", result());
    
    return 0;
}


int dfs(int x, int y, int point, int depth, int limit) {
    int i, h = 0, v, tmp;
    for(i = 0; i < N*N; i++) {
        v = map[i/N][i%N];
        if(v) {
            v--;
            h += abs(i/N-v/N)+abs(i%N-v%N);
        }
    }
    if(h == 0) return depth;
    if(depth+h > limit) return -1;

    for(i = 0; i < N; i++) {
        int nx = x+dx[i], ny = y+dy[i], res;
        if(~point && i == (point+2)%N) continue;
        if(!(0<=nx && nx<N && 0<=ny && ny<N)) continue;
        tmp = map[y][x];
        map[y][x] = map[ny][nx];
        map[ny][nx] = tmp;
        res = dfs(nx, ny, i, depth+1, limit);
        if(~res) return res;
        tmp = map[y][x];
        map[y][x] = map[ny][nx];
        map[ny][nx] = tmp;
    }

    return -1;
}

int result() {
    int x, y, ans, i, j, flg = 0, limit;
    for(i = 0; i < N; i++) {
        for(j = 0; j < N; j++) {
            if(!map[i][j]) {
                x = j;
                y = i;
                flg = 1;
                break;
            }
        }
        if(flg) break;
    }
    for (limit = 0; limit < 100; limit++) {
        for (i = 0; i < N; i++) {
            for (j = 0; j < N; j++) {
                cpy[i][j] = map[i][j];
            }
        }
        if((ans = dfs(x, y, -1, 0, limit)) != -1) return ans;
        for (i = 0; i < N; i++) {
            for (j = 0; j < N; j++) {
                map[i][j] = cpy[i][j];
            }
        }
    }
    return -1;
}