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

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
using namespace std;

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

enum { migi, hidari, mae, ushiro, ccw, cw };
int dx[] = {0, 0, 1, -1, 0, 0};
int dy[] = {1, -1, 0, 0, 0, 0};
int op[7][4] = {
    {0, 0, 0, 0}, {6, 6, 3, 3}, {4, 4, 5, 5}, {5, 5, 1, 1},
    {2, 2, 6, 6}, {3, 3, 2, 2}, {1, 1, 4, 4},
};

int roll(int old, int dir) { return op[old][dir]; }

const int EMPTY = 0;
const int WHITE = 0;
const int BLUE = 1;
const int RED = 2;

char goal[3][3];

struct State {
  int step;
  char t[3][3];

  int HashCode() {
    int h = 0;
    REP(i, 3) REP(j, 3) { h = h * 7 + t[i][j]; }
    return h;
  }
};

State Decode(int h, int step) {
  State state;
  state.step = step;
  for (int i = 2; i >= 0; i--)
    for (int j = 2; j >= 0; j--) {
      state.t[i][j] = h % 7;
      h /= 7;
    }
  return state;
}

bool isGoal(State &state) {
  REP(i, 3) REP(j, 3) {
    if (goal[i][j] == 'E') {
      if (state.t[i][j] != EMPTY)
        return false;
    }
    if (goal[i][j] == 'W') {
      if (state.t[i][j] != 1 && state.t[i][j] != 2)
        return false;
    }

    if (goal[i][j] == 'B') {
      if (state.t[i][j] != 3 && state.t[i][j] != 4)
        return false;
    }

    if (goal[i][j] == 'R') {
      if (state.t[i][j] != 5 && state.t[i][j] != 6)
        return false;
    }
  }
  return true;
}

unsigned char visited[(40353607 + 7) / 8];

bool GetVisited(int h) { return visited[h >> 3] & (1 << (h & 7)); }

void SetVisited(int h) { visited[h >> 3] |= (1 << (h & 7)); }

int Solve(int x, int y) {
  memset(visited, 0, sizeof(visited));

  State start;
  start.step = 0;
  REP(i, 3) REP(j, 3) {
    if (x == i && y == j) {
      start.t[i][j] = EMPTY;
    } else {
      start.t[i][j] = 1;
    }
  }

  queue<State> up;
  up.push(start);
  SetVisited(start.HashCode());

  while (!up.empty()) {
    State cur = up.front();
    up.pop();

    if (cur.step > 30)
      break;

    if (isGoal(cur)) {
      return cur.step;
    }

    REP(x, 3) REP(y, 3) {
      if (cur.t[x][y] == EMPTY) {
        REP(k, 4) {
          int nx = x - dx[k];
          int ny = y - dy[k];
          if (0 <= nx && nx < 3 && 0 <= ny && ny < 3) {
            State next = cur;

            next.t[x][y] = roll(cur.t[nx][ny], k);
            next.t[nx][ny] = EMPTY;

            int h = next.HashCode();
            if (GetVisited(h))
              continue;
            SetVisited(h);

            next.step++;
            up.push(next);
          }
        }
        break;
      }
    }
  }

  return -1;
}

int main() {
  while (1) {
    int x, y;
    scanf("%d%d", &x, &y);
    if (x == 0 && y == 0)
      break;

    REP(i, 3) REP(j, 3) { scanf(" %c", &goal[j][i]); }

    cout << Solve(x - 1, y - 1) << endl;
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
using namespace std;

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

enum { migi, hidari, mae, ushiro, ccw, cw };
int dx[] = {0, 0, 1, -1, 0, 0};
int dy[] = {1, -1, 0, 0, 0, 0};
int op[7][4] = {
    {0, 0, 0, 0}, {6, 6, 3, 3}, {4, 4, 5, 5}, {5, 5, 1, 1},
    {2, 2, 6, 6}, {3, 3, 2, 2}, {1, 1, 4, 4},
};

int roll(int old, int dir) { return op[old][dir]; }

const int EMPTY = 0;
const int WHITE = 0;
const int BLUE = 1;
const int RED = 2;

char goal[3][3];

struct State {
  int step;
  char t[3][3];

  int HashCode() {
    int h = 0;
    REP(i, 3) REP(j, 3) { h = h * 7 + t[i][j]; }
    return h;
  }
};

State Decode(int h, int step) {
  State state;
  state.step = step;
  for (int i = 2; i >= 0; i--)
    for (int j = 2; j >= 0; j--) {
      state.t[i][j] = h % 7;
      h /= 7;
    }
  return state;
}

bool isGoal(State &state) {
  REP(i, 3) REP(j, 3) {
    if (goal[i][j] == 'E') {
      if (state.t[i][j] != EMPTY)
        return false;
    }
    if (goal[i][j] == 'W') {
      if (state.t[i][j] != 1 && state.t[i][j] != 2)
        return false;
    }

    if (goal[i][j] == 'B') {
      if (state.t[i][j] != 3 && state.t[i][j] != 4)
        return false;
    }

    if (goal[i][j] == 'R') {
      if (state.t[i][j] != 5 && state.t[i][j] != 6)
        return false;
    }
  }
  return true;
}

unsigned char visited[40353607 + 7 / 8];

bool GetVisited(int h) { return visited[h >> 3] & (1 << (h & 7)); }

void SetVisited(int h) { visited[h >> 3] |= (1 << (h & 7)); }

int Solve(int x, int y) {
  memset(visited, 0, sizeof(visited));

  State start;
  start.step = 0;
  REP(i, 3) REP(j, 3) {
    if (x == i && y == j) {
      start.t[i][j] = EMPTY;
    } else {
      start.t[i][j] = 1;
    }
  }

  queue<int> up;
  queue<int> up2;

  up.push(start.HashCode());
  up2.push(0);
  SetVisited(start.HashCode());

  while (!up.empty()) {
    State cur = Decode(up.front(), up2.front());
    up.pop();
    up2.pop();

    if (cur.step > 30)
      break;

    if (isGoal(cur)) {
      return cur.step;
    }

    REP(x, 3) REP(y, 3) {
      if (cur.t[x][y] == EMPTY) {
        REP(k, 4) {
          int nx = x - dx[k];
          int ny = y - dy[k];
          if (0 <= nx && nx < 3 && 0 <= ny && ny < 3) {
            State next = cur;

            next.t[x][y] = roll(cur.t[nx][ny], k);
            next.t[nx][ny] = EMPTY;

            int h = next.HashCode();
            if (GetVisited(h))
              continue;
            SetVisited(h);

            up.push(h);
            up2.push(cur.step + 1);
          }
        }
        break;
      }
    }
  }

  return -1;
}

int main() {
  while (1) {
    int x, y;
    scanf("%d%d", &x, &y);
    if (x == 0 && y == 0)
      break;

    REP(i, 3) REP(j, 3) { scanf(" %c", &goal[j][i]); }

    cout << Solve(x - 1, y - 1) << endl;
  }
  return 0;
}