Problem p02246 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <iostream>
#include <map>
#include <queue>
#include <vector>
#define N 4
#define N2 16
using namespace std;

vector<int> move_list[N2];
int dist[N2][N2];

class Game {
public:
  char board[N2];
  char w;
  vector<char> route;
  char mnh;

  bool operator<(const Game &other) const {
    return route.size() + mnh > other.route.size() + other.mnh;
  }
};
Game start;

vector<char> search() {
  priority_queue<Game> q;
  q.push(start);

  while (!q.empty()) {
    Game g = q.top();
    q.pop();
    if (g.mnh == 0)
      return g.route;

    for (int move : move_list[g.w]) {
      if (g.route.size() > 0 && g.route.back() == -move)
        continue;
      Game h = g;
      int to = h.w + move;
      h.mnh -= dist[to][h.board[to] - 1];
      h.mnh += dist[h.w][h.board[to] - 1];
      swap(h.board[h.w], h.board[to]);
      h.w = to;
      h.route.push_back(move);
      q.push(h);
    }
  }
}

int solve() {
  vector<char> route = search();
  return route.size();
}

void initialize() {
  for (int i = 0; i < N2; i++) {
    if (i % N < N - 1)
      move_list[i].push_back(1);
    if (i % N > 0)
      move_list[i].push_back(-1);
    if (i / N < N - 1)
      move_list[i].push_back(N);
    if (i / N > 0)
      move_list[i].push_back(-N);
  }

  // i=board,j=piece-1
  for (int i = 0; i < N2; i++) {
    for (int j = 0; j < N2; j++) {
      dist[i][j] = abs(j % N - i % N) + abs(j / N - i / N);
    }
  }

  start.mnh = 0;
  for (int i = 0; i < N2; i++) {
    if (i == start.w)
      continue;
    start.mnh += dist[i][start.board[i] - 1];
  }
}

int main() {
  int tmp;
  for (int i = 0; i < N2; i++) {
    cin >> tmp;
    if (tmp == 0) {
      start.board[i] = N2;
      start.w = i;
    } else {
      start.board[i] = tmp;
    }
  }
  initialize();
  cout << solve() << endl;
}


Error: MLE

Fixed submission:

#include <array>
#include <iostream>
#include <queue>
#include <set>
#include <vector>

using namespace std;

const int N = 4;

struct Puzzle {
  array<array<int, N>, N> board;
  array<int, 2> empty;
  int cost;

  bool operator<(const Puzzle &p) const {
    for (int i = 0; i < N; ++i) {
      for (int j = 0; j < N; ++j) {
        if (board[i][j] != p.board[i][j])
          return board[i][j] < p.board[i][j];
      }
    }
    return false;
  }
};

int distance(const Puzzle &p) {
  const auto M = N - 1;
  int d = 0;
  for (int i = 0; i < N; ++i) {
    for (int j = 0; j < N; ++j) {
      auto x = p.board[i][j];
      if (x == 0)
        x = 16;
      auto m = (x - 1) % N;
      auto n = (x - 1) / N;

      auto dx = i - m;
      auto dy = j - n;
      if (dx < 0)
        dx = -dx;
      if (dy < 0)
        dy = -dy;
      d += dx + dy;
    }
  }
  return d;
}

struct State {
  Puzzle puzzle;
  int rank;

  bool operator<(const State &other) const { return rank > other.rank; }
};

const vector<array<int, 2>> dir = {
    {-1, 0}, // left
    {0, -1}, // up
    {1, 0},  // right
    {0, 1},  // down
};

bool solved(const Puzzle &p) {
  const auto M = N - 1;
  for (int i = 0; i < N; ++i) {
    for (int j = 0; j < N; ++j) {
      int x = i == M && j == M ? 0 : i * N + j + 1;
      if (p.board[i][j] != x) {
        return false;
      }
    }
  }
  return true;
}

int main() {
  Puzzle start;
  start.cost = 0;
  for (int i = 0; i < N; ++i) {
    for (int j = 0; j < N; ++j) {
      int x;
      cin >> x;
      if (x == 0) {
        start.empty = {i, j};
      }
      start.board[i][j] = x;
    }
  }

  Puzzle ans;
  set<Puzzle> visited;
  priority_queue<State> Q;
  Q.push(State{start, distance(start)});
  while (!Q.empty()) {
    auto state = Q.top();
    Q.pop();
    auto u = state.puzzle;
    if (solved(u)) {
      ans = std::move(u);
      break;
    }
    for (auto &d : dir) {
      auto tx = u.empty[0] + d[0];
      auto ty = u.empty[1] + d[1];
      if (tx < 0 || ty < 0 || tx >= N || ty >= N) {
        continue;
      }
      auto v = u;
      swap(v.board[v.empty[0]][v.empty[1]], v.board[tx][ty]);
      v.empty = {tx, ty};
      ++v.cost;
      if (visited.find(v) == visited.end()) {
        visited.insert(v);
        Q.push(State{v, v.cost + distance(v)});
      }
    }
  }
  cout << ans.cost << endl;

  return 0;
}