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

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using namespace std;

// ---------------------
// repetition
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

// debug
#define dump(x) cerr << #x << " = " << (x) << endl;
#define debug(x)                                                               \\
  cerr << #x << " = " << (x) << " (L" << __LINE__ << ")"                       \\
       << " " << __FILE__ << endl;

// ---------------------
#define INF 922337203685477580
#define IINF (1 << 21)
typedef long long ll;

class Board {
public:
  int board[3][3];
  Board() {}
  Board(int b[3][3]) {
    REP(i, 3) {
      REP(j, 3) { board[i][j] = b[i][j]; }
    }
  }

  int hash() {
    int accum = 0;
    int digit = 1;
    REP(i, 3) {
      REP(j, 3) {
        accum += board[i][j] * digit;
        digit *= 10;
      }
    }
    return accum;
  }
  string to_str() {
    string str = "";
    REP(i, 3) {
      REP(j, 3) { str += " " + to_string(board[i][j]); }
      str += "\\n";
    }
    return str;
  }
  bool operator==(const Board &other) {
    REP(i, 3) {
      REP(j, 3) {
        if (board[i][j] != other.board[i][j]) {
          return false;
        }
      }
    }
    return true;
  }
};

class Nully;
static Board Nully;

Board swap_with_upper(const Board &b) {
  int pos_i, pos_j;
  REP(i, 3) {
    REP(j, 3) {
      if (b.board[i][j] == 0) {
        pos_i = i;
        pos_j = j;
        break;
      }
    }
  }
  if (pos_i == 0) {
    return Nully;
  }

  Board next = b;
  swap(next.board[pos_i][pos_j], next.board[pos_i - 1][pos_j]);
  return next;
}
Board swap_with_lower(const Board &b) {
  int pos_i, pos_j;
  REP(i, 3) {
    REP(j, 3) {
      if (b.board[i][j] == 0) {
        pos_i = i;
        pos_j = j;
        break;
      }
    }
  }
  if (pos_i == 2) {
    return Nully;
  }

  Board next = b;
  swap(next.board[pos_i][pos_j], next.board[pos_i + 1][pos_j]);
  return next;
}
Board swap_with_left(const Board &b) {
  int pos_i, pos_j;
  REP(i, 3) {
    REP(j, 3) {
      if (b.board[i][j] == 0) {
        pos_i = i;
        pos_j = j;
        break;
      }
    }
  }
  if (pos_j == 0) {
    return Nully;
  }

  Board next = b;
  swap(next.board[pos_i][pos_j], next.board[pos_i][pos_j - 1]);
  return next;
}
Board swap_with_right(const Board &b) {
  int pos_i, pos_j;
  REP(i, 3) {
    REP(j, 3) {
      if (b.board[i][j] == 0) {
        pos_i = i;
        pos_j = j;
        break;
      }
    }
  }
  if (pos_j == 2) {
    return Nully;
  }

  Board next = b;
  swap(next.board[pos_i][pos_j], next.board[pos_i][pos_j + 1]);
  return next;
}

int main() {
  // int b[3][3] = {{1, 3, 0}, {4, 2, 5}, {7, 8, 6}};
  int b[3][3];
  REP(i, 3) {
    REP(j, 3) { cin >> b[i][j]; }
  }

  int g[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 0}};
  Board init(b);
  Board goal(g);
  // cout << init.to_str() << endl;

  int depth = 0;
  queue<pair<Board, int>> Q;
  set<int> S;
  Q.push(make_pair(init, depth));
  S.insert(init.hash());

  while (!Q.empty()) {
    Board current = Q.front().first;
    Board next;
    int dpt = Q.front().second;
    Q.pop();

    if (goal == current) {
      cout << dpt << endl;
      return 0;
    }

    next = swap_with_upper(current);
    if (!(next == Nully) && S.count(next.hash()) == 0) {
      Q.push(make_pair(next, dpt + 1));
      S.insert(next.hash());
    }
    next = swap_with_lower(current);
    if (!(next == Nully) && S.count(next.hash()) == 0) {
      Q.push(make_pair(next, dpt + 1));
      S.insert(next.hash());
    }
    next = swap_with_left(current);
    if (!(next == Nully) && S.count(next.hash()) == 0) {
      Q.push(make_pair(next, dpt + 1));
      S.insert(next.hash());
    }
    next = swap_with_right(current);
    if (!(next == Nully) && S.count(next.hash()) == 0) {
      Q.push(make_pair(next, dpt + 1));
      S.insert(next.hash());
    }
  }

  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using namespace std;

// ---------------------
// repetition
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

// debug
#define dump(x) cerr << #x << " = " << (x) << endl;
#define debug(x)                                                               \\
  cerr << #x << " = " << (x) << " (L" << __LINE__ << ")"                       \\
       << " " << __FILE__ << endl;

// ---------------------
#define INF 922337203685477580
#define IINF (1 << 21)
typedef long long ll;

class Board {
public:
  int board[3][3];
  Board() {}
  Board(int b[3][3]) {
    REP(i, 3) {
      REP(j, 3) { board[i][j] = b[i][j]; }
    }
  }

  int hash() {
    int accum = 0;
    int digit = 1;
    REP(i, 3) {
      REP(j, 3) {
        accum += board[i][j] * digit;
        digit *= 10;
      }
    }
    return accum;
  }
  string to_str() {
    string str = "";
    REP(i, 3) {
      REP(j, 3) { str += " " + to_string(board[i][j]); }
      str += "\\n";
    }
    return str;
  }
  bool operator==(const Board &other) {
    REP(i, 3) {
      REP(j, 3) {
        if (board[i][j] != other.board[i][j]) {
          return false;
        }
      }
    }
    return true;
  }
};

class Nully;
static Board Nully;

Board swap_with_upper(const Board &b) {
  int pos_i, pos_j;
  REP(i, 3) {
    REP(j, 3) {
      if (b.board[i][j] == 0) {
        pos_i = i;
        pos_j = j;
        break;
      }
    }
  }
  if (pos_i == 0) {
    return Nully;
  }

  Board next = b;
  swap(next.board[pos_i][pos_j], next.board[pos_i - 1][pos_j]);
  return next;
}
Board swap_with_lower(const Board &b) {
  int pos_i, pos_j;
  REP(i, 3) {
    REP(j, 3) {
      if (b.board[i][j] == 0) {
        pos_i = i;
        pos_j = j;
        break;
      }
    }
  }
  if (pos_i == 2) {
    return Nully;
  }

  Board next = b;
  swap(next.board[pos_i][pos_j], next.board[pos_i + 1][pos_j]);
  return next;
}
Board swap_with_left(const Board &b) {
  int pos_i, pos_j;
  REP(i, 3) {
    REP(j, 3) {
      if (b.board[i][j] == 0) {
        pos_i = i;
        pos_j = j;
        break;
      }
    }
  }
  if (pos_j == 0) {
    return Nully;
  }

  Board next = b;
  swap(next.board[pos_i][pos_j], next.board[pos_i][pos_j - 1]);
  return next;
}
Board swap_with_right(const Board &b) {
  int pos_i, pos_j;
  REP(i, 3) {
    REP(j, 3) {
      if (b.board[i][j] == 0) {
        pos_i = i;
        pos_j = j;
        break;
      }
    }
  }
  if (pos_j == 2) {
    return Nully;
  }

  Board next = b;
  swap(next.board[pos_i][pos_j], next.board[pos_i][pos_j + 1]);
  return next;
}

int main() {
  // int b[3][3] = {{1, 3, 0}, {4, 2, 5}, {7, 8, 6}};
  int b[3][3];
  REP(i, 3) {
    REP(j, 3) { cin >> b[i][j]; }
  }

  int g[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 0}};
  Board init(b);
  Board goal(g);
  // cout << init.to_str() << endl;

  int depth = 0;
  queue<pair<Board, int>> Q;
  Q.push(make_pair(init, depth));

  while (!Q.empty()) {
    Board current = Q.front().first;
    Board next;
    int dpt = Q.front().second;
    Q.pop();

    if (goal == current) {
      cout << dpt << endl;
      return 0;
    }

    next = swap_with_upper(current);
    if (!(next == Nully)) {
      Q.push(make_pair(next, dpt + 1));
    }
    next = swap_with_lower(current);
    if (!(next == Nully)) {
      Q.push(make_pair(next, dpt + 1));
    }
    next = swap_with_left(current);
    if (!(next == Nully)) {
      Q.push(make_pair(next, dpt + 1));
    }
    next = swap_with_right(current);
    if (!(next == Nully)) {
      Q.push(make_pair(next, dpt + 1));
    }
  }

  return 0;
}