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

#include <bits/stdc++.h>
using namespace std;

const int LEFT = 0, RIGHT = 1, FRONT = 2, BACK = 3, BOTTOM = 4, TOP = 5;

class Dice {
public:
  int val[6];
  Dice() {
    for (int i = 0; i < 6; i++)
      val[i] = i;
  }
  Dice(int val[6]) {
    for (int i = 0; i < 6; i++)
      this->val[i] = val[i];
  }

  void rot(string s) {
    if (s == "N" || s == "B")
      rotN();
    else if (s == "S" || s == "F")
      rotS();
    else if (s == "E" || s == "R")
      rotE();
    else if (s == "W" || s == "L")
      rotW();
    else if (s == "CW")
      rotCW();
    else if (s == "CCW")
      rotCCW();
    else
      assert(!"rot error"); /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
  }

  void rot(char ch) { rot(string(1, ch)); }

  // 奥に転がす
  void rotN() {
    swap(val[TOP], val[FRONT]);
    swap(val[FRONT], val[BOTTOM]);
    swap(val[BOTTOM], val[BACK]);
  }

  // 手前に転がす
  void rotS() {
    // rotN(),rotN(),rotN();
    swap(val[TOP], val[BACK]);
    swap(val[BACK], val[BOTTOM]);
    swap(val[BOTTOM], val[FRONT]);
  }

  // 右に転がす
  void rotE() {
    swap(val[TOP], val[LEFT]);
    swap(val[LEFT], val[BOTTOM]);
    swap(val[BOTTOM], val[RIGHT]);
  }

  // 左に転がす
  void rotW() {
    // rotE(),rotE(),rotE();
    swap(val[TOP], val[RIGHT]);
    swap(val[RIGHT], val[BOTTOM]);
    swap(val[BOTTOM], val[LEFT]);
  }

  // 上から見て時計回りに回す
  void rotCW() {
    swap(val[FRONT], val[RIGHT]);
    swap(val[RIGHT], val[BACK]);
    swap(val[BACK], val[LEFT]);
  }

  // 上からみて反時計回りに回す。
  void rotCCW() {
    // rotCW(),rotCW(),rotCW();
    swap(val[FRONT], val[LEFT]);
    swap(val[LEFT], val[BACK]);
    swap(val[BACK], val[RIGHT]);
  }
};

int dy[300], dx[300];

void init() {

  dy['N'] = 1;
  dy['E'] = 0;
  dy['S'] = -1;
  dy['W'] = 0;

  dx['N'] = 0;
  dx['E'] = 1;
  dx['S'] = 0;
  dx['W'] = -1;
}

int n, x[15], y[15], to[2500][2500], fromx[500], fromy[500];
string s[15];
Dice dice[15];

typedef pair<int, int> P;

const int M = 15 * 30;
const int pepi = 1250;

void compress() {

  map<P, int> used;

  for (int idx = 0; idx < n; idx++) {

    int X = x[idx] + pepi, Y = y[idx] + pepi;

    Dice d = dice[idx];

    used[P(X, Y)] = 0;

    for (int i = 0; i < (int)s[idx].size(); i++) {

      X += dx[(int)s[idx][i]];

      Y += dy[(int)s[idx][i]];

      d.rot(s[idx][i]);

      used[P(X, Y)] = 0;
    }
  }

  int idx = 0;

  auto p = used.begin();

  while (p != used.end()) {

    int x = (*p).first.first;

    int y = (*p).first.second;

    to[x][y] = idx;

    fromx[idx] = x;

    fromy[idx] = y;

    idx++;

    p++;
  }
}

int memo[2500][2500], maxs[1 << 15];
bitset<M> dp[1 << 15];

void update(bitset<M> S, int idx, int I, int nI) {

  int sum = maxs[I];

  int X = fromx[to[x[idx] + pepi][y[idx] + pepi]];
  int Y = fromy[to[x[idx] + pepi][y[idx] + pepi]];

  Dice d = dice[idx];

  unordered_set<int> used;

  if (S[to[X][Y]] == 0) {
    S[to[X][Y]] = 1;
    used.insert(to[X][Y]);
    sum += d.val[BOTTOM];
    memo[X][Y] = d.val[BOTTOM];
  }

  for (int i = 0; i < (int)s[idx].size(); i++) {

    X += dx[(int)s[idx][i]];

    Y += dy[(int)s[idx][i]];

    d.rot(s[idx][i]);

    if (used.count(to[X][Y])) {
      sum -= memo[X][Y];
      sum += d.val[BOTTOM];
      memo[X][Y] = d.val[BOTTOM];
    }

    if (S[to[X][Y]] == 0) {
      S[to[X][Y]] = 1;
      used.insert(to[X][Y]);
      sum += d.val[BOTTOM];
      memo[X][Y] = d.val[BOTTOM];
    }
  }

  if (maxs[nI] < sum) {
    maxs[nI] = sum;
    dp[nI] = S;
  }
}

signed main() {

  init();

  while (1) {

    cin >> n;
    if (n == 0)
      break;

    for (int i = 0; i < (1 << n); i++)
      dp[i] = maxs[i] = 0;

    for (int i = 0; i < n; i++) {

      cin >> x[i] >> y[i];

      int val[6];

      for (int j = 0; j < 6; j++)
        cin >> val[j];

      dice[i] = Dice(val);

      cin >> s[i];

      for (int j = 0; j < (int)s[i].size(); j++) {
        if (s[i][j] == 'B')
          s[i][j] = 'N';
        if (s[i][j] == 'R')
          s[i][j] = 'E';
        if (s[i][j] == 'F')
          s[i][j] = 'S';
        if (s[i][j] == 'L')
          s[i][j] = 'W';
      }
    }

    compress();

    for (int i = 0; i < (1 << n); i++) {

      for (int j = 0; j < n; j++) {

        if (!(i >> j & 1))
          update(dp[i], j, i, i | (1 << j));
      }
    }

    cout << maxs[(1 << n) - 1] << endl;
  }

  return 0;
}


Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

const int LEFT = 0, RIGHT = 1, FRONT = 2, BACK = 3, BOTTOM = 4, TOP = 5;

class Dice {
public:
  int val[6];
  Dice() {
    for (int i = 0; i < 6; i++)
      val[i] = i;
  }
  Dice(int val[6]) {
    for (int i = 0; i < 6; i++)
      this->val[i] = val[i];
  }

  void rot(string s) {
    if (s == "N" || s == "B")
      rotN();
    else if (s == "S" || s == "F")
      rotS();
    else if (s == "E" || s == "R")
      rotE();
    else if (s == "W" || s == "L")
      rotW();
    else if (s == "CW")
      rotCW();
    else if (s == "CCW")
      rotCCW();
    else
      assert(!"rot error"); /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
  }

  void rot(char ch) { rot(string(1, ch)); }

  // 奥に転がす
  void rotN() {
    swap(val[TOP], val[FRONT]);
    swap(val[FRONT], val[BOTTOM]);
    swap(val[BOTTOM], val[BACK]);
  }

  // 手前に転がす
  void rotS() {
    // rotN(),rotN(),rotN();
    swap(val[TOP], val[BACK]);
    swap(val[BACK], val[BOTTOM]);
    swap(val[BOTTOM], val[FRONT]);
  }

  // 右に転がす
  void rotE() {
    swap(val[TOP], val[LEFT]);
    swap(val[LEFT], val[BOTTOM]);
    swap(val[BOTTOM], val[RIGHT]);
  }

  // 左に転がす
  void rotW() {
    // rotE(),rotE(),rotE();
    swap(val[TOP], val[RIGHT]);
    swap(val[RIGHT], val[BOTTOM]);
    swap(val[BOTTOM], val[LEFT]);
  }

  // 上から見て時計回りに回す
  void rotCW() {
    swap(val[FRONT], val[RIGHT]);
    swap(val[RIGHT], val[BACK]);
    swap(val[BACK], val[LEFT]);
  }

  // 上からみて反時計回りに回す。
  void rotCCW() {
    // rotCW(),rotCW(),rotCW();
    swap(val[FRONT], val[LEFT]);
    swap(val[LEFT], val[BACK]);
    swap(val[BACK], val[RIGHT]);
  }
};

int dy[300], dx[300];

void init() {

  dy['N'] = 1;
  dy['E'] = 0;
  dy['S'] = -1;
  dy['W'] = 0;

  dx['N'] = 0;
  dx['E'] = 1;
  dx['S'] = 0;
  dx['W'] = -1;
}

int n, x[15], y[15];
string s[15];
Dice dice[15];

typedef pair<int, int> P;

map<P, int> dp[1 << 15];

int sum(map<P, int> S) {
  int res = 0;
  for (auto p : S)
    res += p.second;
  return res;
}

map<P, int> add(map<P, int> S, int idx) {

  int X = x[idx], Y = y[idx];

  Dice d = dice[idx];

  set<P> used;

  if (S.count(P(X, Y)) == 0) {
    S[P(X, Y)] = d.val[BOTTOM];
    used.insert(P(X, Y));
  }

  for (int i = 0; i < (int)s[idx].size(); i++) {

    X += dx[(int)s[idx][i]];

    Y += dy[(int)s[idx][i]];

    d.rot(s[idx][i]);

    if (used.count(P(X, Y)) || S.count(P(X, Y)) == 0) {
      S[P(X, Y)] = d.val[BOTTOM];
      used.insert(P(X, Y));
    }
  }

  return S;
}

signed main() {

  init();

  while (1) {

    cin >> n;
    if (n == 0)
      break;

    for (int i = 0; i < (1 << n); i++)
      dp[i].clear();

    for (int i = 0; i < n; i++) {

      cin >> x[i] >> y[i];

      int val[6];

      for (int j = 0; j < 6; j++)
        cin >> val[j];

      dice[i] = Dice(val);

      cin >> s[i];

      for (int j = 0; j < (int)s[i].size(); j++) {
        if (s[i][j] == 'B')
          s[i][j] = 'N';
        if (s[i][j] == 'R')
          s[i][j] = 'E';
        if (s[i][j] == 'F')
          s[i][j] = 'S';
        if (s[i][j] == 'L')
          s[i][j] = 'W';
      }
    }

    for (int i = 0; i < (1 << n); i++) {

      for (int j = 0; j < n; j++) {

        if (!(i >> j & 1)) {

          if (sum(dp[i | (1 << j)]) < sum(add(dp[i], j))) {

            dp[i | (1 << j)] = add(dp[i], j);
          }
        }
      }
    }

    cout << sum(dp[(1 << n) - 1]) << endl;
  }

  return 0;
}