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 tate 4
#define yoko 4
#define Total (tate*yoko)

extern inline void down_0(void);
extern inline void up_0(void);
extern inline void right_0(void);
extern inline void left_0(void);

extern int  serch(int x, int y, int MaxCnt, int pre);
extern int  check(void);

int cnt,num = 0;
int val[Total] ={};


int main( void )
{
    int i = 0;
    int x,y = 0;
    
    for(i=0; i<Total; i++)
    {
        scanf("%d",&val[i]);
        
        if(val[i] == 0)
        {
            num = i;
        }
    }
    
    x = tate - (num/yoko) -1;
    y = yoko - (num%yoko) -1;
    
//    printf("%d,%d\n",x,y);
    
    for(i=0; i<45; i++)
    {
        if( serch(x,y,i,4) == 1 )
        {
            printf("%d\n",i);
            break;
        }
    }     
    
    return 0;
}

int serch(int x, int y, int MaxCnt, int pre)
{
    int result;
    int i=0;
    
    // 最大数で打ち切り
    if(MaxCnt==0)
    {
        return check();
    }
    
    for(i=0; i<4; i++)
    {
        result = 0;
        
        switch(i)
        {
            case 0:
                if( (x > 0) && (pre != 3) )
                {
                    down_0();
                    
                    result = serch(x-1, y, MaxCnt-1, 0);
                    
                    up_0();
                }
                break;
            case 1:
                if( (y > 0) && (pre != 2) )
                {
                    right_0();
                    
                    result = serch(x, y-1, MaxCnt-1, 1);
                    
                    left_0();
                }
                break;
            case 2:
                if( (y < yoko -1 ) && (pre != 1) )
                {
                    left_0();
                    
                    result = serch(x, y+1, MaxCnt-1, 2);
                    
                    right_0();
                }
                break;
            case 3:
                if( (x < tate -1 ) && (pre != 0) )
                {
                    up_0();
                    
                    result = serch(x+1, y, MaxCnt-1, 3);
                    
                    down_0();
                }
                break;
            default:
                break;
        }
        
        if(result)
        {
            return 1;
        }
        
    }

    return 0;
}

// TRUE : 完成
// FALSE : 失敗
int check()
{
    int i=0;
    
//    printf("%d%d%d%d%d%d%d%d%d\n", val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8]);
    
    for(i=0; i<Total-1; i++)
    {
        if(val[i] != (i+1))
        {
            return 0;
        }
    }
    return 1;
}

inline void down_0()
{
    val[num] = val[num + yoko];
    num = num + yoko;
}
 
inline void up_0()
{
    val[num] = val[num - yoko];
    num = num - yoko;
}
 
inline void right_0()
{
    val[num] = val[num +1];
    num = num + 1;
}
 
inline void left_0()
{
    val[num] = val[num -1];
    num = num - 1;
}