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++11 (judge verdict: Memory Limit Exceeded)

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <sstream>
#include <string>
#include <utility>
#include <map>
#include <memory>
#include <set>
#include <vector>
#include <deque>
#include <list>
#include <stack>
#include <queue>

using namespace std;

class Board
{
public:
  vector<vector<int>> fld;
  int sr, sc;
  int dist, cost;
  static vector<vector<vector<int>>> dt;
  bool operator < ( const Board& b ) const
  {
    for ( auto i = 0; i < 4; ++i )
      for ( auto j = 0; j < 4; ++j )
        {
          if ( fld[i][j] != b.fld[i][j] )
            return fld[i][j] < b.fld[i][j];
        }
    return false;
  }
  void print()
  {
    for ( auto i = 0; i < 4; ++i )
      {
        for ( auto j = 0; j < 4; ++j )
          cout << " " << fld[i][j] + 1;
        cout << endl;
      }
    cout << sr << " " << sc << endl;
    cout << dist << " " << cost << endl;
  }
  void calcdist();
};

vector<vector<vector<int>>> Board::dt(4, vector<vector<int>>(4, vector<int>(16)));

void Board::calcdist()
{
  dist = 0;
  for ( auto i = 0; i < 4; ++i )
    for ( auto j = 0; j < 4; ++j )
      dist += dt[i][j][fld[i][j]];
}

class State
{
public:
  Board bd;
  int h;
  bool operator < ( const State& s ) const
  {
    return h > s.h;
  }
};

class FifteenPuzzle
{
public:
  priority_queue<State> pq;
  map<Board,bool> m;
  vector<int> dr,dc;
  FifteenPuzzle(){}
  FifteenPuzzle( State st )
  {
    pq.push(st);
    m[st.bd] = true;
    dr = {1, -1, 0, 0}; dc = {0, 0, 1, -1};
  }
  int solve();
};

int FifteenPuzzle::solve()
{
  State nst;
  
  while ( ! pq.empty() )
    {
      State st = pq.top();
      pq.pop();
      
      Board b = st.bd;
      
      if ( b.dist == 0 )
        {
          cout << b.cost << endl;
          return 0;
        }

      for ( auto i = 0; i < 4; ++i )
        {
          int nr = b.sr + dr[i];
          int nc = b.sc + dc[i];
          if ( nr < 0 || nr > 3 || nc < 0 || nc > 3 ) continue;

          Board nb = b;
          nb.fld[b.sr][b.sc] = b.fld[nr][nc];
          nb.fld[nr][nc] = 15;
          nb.sr = nr;
          nb.sc = nc;
          nb.cost = b.cost + 1;
          nb.calcdist();
          
          if ( m.count(nb) == 0 )
            {
              State nst;
              nst.bd = nb;
              nst.h = nb.cost + nb.dist;
              pq.push(nst);
              m[nb] = true;
            }
        }
    }
  
  return 0;
}

int main()
{

  for ( auto i = 0; i < 4; ++i )
    for ( auto j = 0; j < 4; ++j )
      for ( auto k = 0; k < 16; ++k )
        Board::dt[i][j][k] = abs(i - k / 4) + abs(j - k % 4);
      
  
  Board b;
  b.cost = 0;
  
  for ( auto i = 0; i < 4; ++i )
    {
      vector<int> vl;
      for ( auto j = 0; j < 4; ++j )
        {
          int v;
          cin >> v;
          
          if ( v == 0 )
            {
              v = 15;
              b.sr = i;
              b.sc = j;
            }
          else
            --v;
          
          vl.push_back(v);
        }
      b.fld.push_back(vl);
    }

  b.calcdist();
  
  State st;
  st.bd = b;
  st.h = b.cost + b.dist;
  
  FifteenPuzzle fp( st );

  fp.solve();

  return 0;
}