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

#include <algorithm>
#include <cstdio>
#include <map>
#include <memory>
#include <queue>

#define rep(i, n) for (int i = 0; i < n; ++i)

using namespace std;

typedef vector<vector<int>> R;
typedef shared_ptr<R> Q;
typedef pair<pair<int, int>, Q> P;

int table[6][4] = {{1, 3, 4, 2}, {0, 2, 5, 3}, {0, 4, 5, 1},
                   {0, 1, 5, 4}, {0, 3, 5, 2}, {1, 2, 4, 3}};

int move(int index, int dx, int dy) {
  int a = index / 4;
  int b = index % 4;
  int s, t;
  if (dx == -1) {
    s = table[a][b];
    t = 5 - a;
  } else if (dx == 1) {
    s = table[a][(b + 2) % 4];
    t = a;
  } else if (dy == -1) {
    s = table[a][(b + 1) % 4];
    t = table[a][b];
  } else {
    s = table[a][(b + 3) % 4];
    t = table[a][b];
  }
  return s * 4 + find(table[s], table[s] + 4, t) - table[s];
}

int n, m;
char g[20][20];
int sx[3];
int sy[3];
int st[3];
int d[3][20][20][24];
map<vector<vector<int>>, int> f;

int approximate(vector<vector<int>> &t) {
  int p[6][3] = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2},
                 {1, 2, 0}, {2, 0, 1}, {2, 1, 0}};

  int u = -1;
  rep(i, 6) {
    int v = d[p[i][0]][t[0][0]][t[0][1]][t[0][2]] +
            d[p[i][1]][t[1][0]][t[1][1]][t[1][2]] +
            d[p[i][2]][t[2][0]][t[2][1]][t[2][2]];
    if (u == -1 || u > v) {
      u = v;
    }
  }
  return u;
}

bool is_reached(vector<vector<int>> &t) {
  int p[6][3] = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2},
                 {1, 2, 0}, {2, 0, 1}, {2, 1, 0}};

  rep(a, 6) {
    bool b = true;
    rep(i, 3) {
      if (!(t[i][0] == sx[p[a][i]] && t[i][1] == sy[p[a][i]] &&
            t[i][2] / 4 == st[p[a][i]])) {
        b = false;
      }
    }
    if (b) {
      return true;
    }
  }
  return false;
}

int main() {
  scanf("%d%d", &n, &m);
  rep(i, n) {
    rep(j, m) { scanf(" %c", &g[i][j]); }
  }

  int t = 0;
  rep(i, n) {
    rep(j, m) {
      if ('1' <= g[i][j] && g[i][j] <= '6') {
        sx[t] = i;
        sy[t] = j;
        st[t] = g[i][j] - '1';
        ++t;
      }
    }
  }
  rep(a, 3) {
    rep(i, n) {
      rep(j, m) {
        rep(k, 24) { d[a][i][j][k] = 10000; }
      }
    }

    queue<vector<int>> q;
    rep(i, 4) {
      d[a][sx[a]][sy[a]][st[a] * 4 + i] = 0;
      q.push({sx[a], sy[a], st[a] * 4 + i});
    }
    while (!q.empty()) {
      auto v = q.front();
      q.pop();
      int dx[4] = {-1, 0, 0, 1};
      int dy[4] = {0, -1, 1, 0};
      rep(i, 4) {
        int x = v[0] + dx[i];
        int y = v[1] + dy[i];
        int index = move(v[2], dx[i], dy[i]);
        if (0 <= x && x < n && 0 <= y && y < m && g[x][y] != 'x' &&
            d[a][x][y][index] == 10000) {
          d[a][x][y][index] = d[a][v[0]][v[1]][v[2]] + 1;
          q.push({x, y, index});
        }
      }
    }
  }

  priority_queue<P, vector<P>, greater<P>> q;
  vector<vector<int>> s;
  rep(i, n) {
    rep(j, m) {
      if (g[i][j] == 'o') {
        s.push_back({i, j, 0});
      }
    }
  }
  q.push({{approximate(s), approximate(s)}, Q(new R(s))});
  while (!q.empty()) {
    /*
    printf("(%d, %d)\\n", q.top().first.first, q.top().first.second);
    */

    auto v = *q.top().second;
    q.pop();
    int dx[4] = {-1, 0, 0, 1};
    int dy[4] = {0, -1, 1, 0};
    rep(a, 3) {
      rep(i, 4) {
        int x = v[a][0] + dx[i];
        int y = v[a][1] + dy[i];
        int index = move(v[a][2], dx[i], dy[i]);
        auto t = v;
        t[a][0] = x;
        t[a][1] = y;
        t[a][2] = index;
        bool b = true;
        rep(j, 3) {
          if (v[j][0] == x && v[j][1] == y) {
            b = false;
          }
        }
        if (0 <= x && x < n && 0 <= y && y < m && g[x][y] != 'x' && b &&
            f.find(t) == f.end()) {
          f[t] = f[v] + 1;
          if (is_reached(t)) {
            printf("%d\\n", f[t]);
            return 0;
          }
          q.push({{approximate(t) + f[t], approximate(t)}, Q(new R(t))});
        }
      }
    }
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <map>
#include <queue>

#define rep(i, n) for (int i = 0; i < n; ++i)

using namespace std;

typedef pair<pair<int, int>, vector<vector<int>>> P;

int table[6][4] = {{1, 3, 4, 2}, {0, 2, 5, 3}, {0, 4, 5, 1},
                   {0, 1, 5, 4}, {0, 3, 5, 2}, {1, 2, 4, 3}};

int move(int index, int dx, int dy) {
  int a = index / 4;
  int b = index % 4;
  int s, t;
  if (dx == -1) {
    s = table[a][b];
    t = 5 - a;
  } else if (dx == 1) {
    s = table[a][(b + 2) % 4];
    t = a;
  } else if (dy == -1) {
    s = table[a][(b + 1) % 4];
    t = table[a][b];
  } else {
    s = table[a][(b + 3) % 4];
    t = table[a][b];
  }
  return s * 4 + find(table[s], table[s] + 4, t) - table[s];
}

int n, m;
char g[20][20];
int sx[3];
int sy[3];
int st[3];
int d[3][20][20][24];
map<vector<vector<int>>, int> f;

int approximate(vector<vector<int>> &t) {
  int p[6][3] = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2},
                 {1, 2, 0}, {2, 0, 1}, {2, 1, 0}};

  int u = -1;
  rep(i, 6) {
    int v = d[p[i][0]][t[0][0]][t[0][1]][t[0][2]] +
            d[p[i][1]][t[1][0]][t[1][1]][t[1][2]] +
            d[p[i][2]][t[2][0]][t[2][1]][t[2][2]];
    if (u == -1 || u > v) {
      u = v;
    }
  }
  return u;
}

bool is_reached(vector<vector<int>> &t) {
  int p[6][3] = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2},
                 {1, 2, 0}, {2, 0, 1}, {2, 1, 0}};

  rep(a, 6) {
    bool b = true;
    rep(i, 3) {
      if (!(t[i][0] == sx[p[a][i]] && t[i][1] == sy[p[a][i]] &&
            t[i][2] / 4 == st[p[a][i]])) {
        b = false;
      }
    }
    if (b) {
      return true;
    }
  }
  return false;
}

int main() {
  scanf("%d%d", &n, &m);
  rep(i, n) {
    rep(j, m) { scanf(" %c", &g[i][j]); }
  }

  int t = 0;
  rep(i, n) {
    rep(j, m) {
      if ('1' <= g[i][j] && g[i][j] <= '6') {
        sx[t] = i;
        sy[t] = j;
        st[t] = g[i][j] - '1';
        ++t;
      }
    }
  }
  rep(a, 3) {
    rep(i, n) {
      rep(j, m) {
        rep(k, 24) { d[a][i][j][k] = 10000; }
      }
    }

    queue<vector<int>> q;
    rep(i, 4) {
      d[a][sx[a]][sy[a]][st[a] * 4 + i] = 0;
      q.push({sx[a], sy[a], st[a] * 4 + i});
    }
    while (!q.empty()) {
      auto v = q.front();
      q.pop();
      int dx[4] = {-1, 0, 0, 1};
      int dy[4] = {0, -1, 1, 0};
      rep(i, 4) {
        int x = v[0] + dx[i];
        int y = v[1] + dy[i];
        int index = move(v[2], dx[i], dy[i]);
        if (0 <= x && x < n && 0 <= y && y < m && g[x][y] != 'x' &&
            d[a][x][y][index] == 10000) {
          d[a][x][y][index] = d[a][v[0]][v[1]][v[2]] + 1;
          q.push({x, y, index});
        }
      }
    }
  }

  priority_queue<P, vector<P>, greater<P>> q;
  vector<vector<int>> s;
  rep(i, n) {
    rep(j, m) {
      if (g[i][j] == 'o') {
        s.push_back({i, j, 0});
      }
    }
  }
  q.push({{approximate(s), approximate(s)}, s});
  while (!q.empty()) {
    /*
    printf("(%d, %d)\\n", q.top().first.first, q.top().first.second);
    */

    auto v = q.top().second;
    q.pop();
    int dx[4] = {-1, 0, 0, 1};
    int dy[4] = {0, -1, 1, 0};
    rep(a, 3) {
      rep(i, 4) {
        int x = v[a][0] + dx[i];
        int y = v[a][1] + dy[i];
        int index = move(v[a][2], dx[i], dy[i]);
        auto t = v;
        t[a][0] = x;
        t[a][1] = y;
        t[a][2] = index;
        bool b = true;
        rep(j, 3) {
          if (v[j][0] == x && v[j][1] == y) {
            b = false;
          }
        }
        if (0 <= x && x < n && 0 <= y && y < m && g[x][y] != 'x' && b &&
            f.find(t) == f.end()) {
          f[t] = f[v] + 1;
          if (is_reached(t)) {
            printf("%d\\n", f[t]);
            return 0;
          }
          q.push({{approximate(t) + f[t], approximate(t)}, t});
        }
      }
    }
  }
  return 0;
}