Problem p01752 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <bits/stdc++.h>

using namespace std;

int Dx[4] = {0, 1, 0, -1};
int Dy[4] = {1, 0, -1, 0};

int dhx[4][4] = {
    {0, 1, 1, 1},
    {1, 1, 0, -1},
    {0, -1, -1, -1},
    {-1, -1, 0, 1},
};
int dhy[4][4] = {
    {1, 1, 0, -1},
    {0, -1, -1, -1},
    {-1, -1, 0, 1},
    {0, 1, 1, 1},
};

struct Node {
  int x, y, hx, hy, dir;
};

int H, W;
int wall[100][100] = {0};
bool used[100][100] = {0};
bool reach[100][100][100][100][4] = {0};
bool inRange(int x, int y) { return 0 <= x && x < W && 0 <= y && y < H; }
bool inRange2(int x, int y) { return -1 <= x && x <= W && -1 <= y && y <= H; }
bool Wall(int x, int y) {
  if (inRange(x, y))
    return wall[y][x];
  return true;
}
bool isInvalidHand(int px, int py, int hx, int hy, int dir) {
  //	cout << ":" << px << " " << py << " " << hx << " " << hy << endl;
  if (!Wall(hx, hy))
    return true;
  for (int i = 0; i < 4; ++i) {
    int x = px + dhx[dir][i];
    int y = py + dhy[dir][i];
    if (inRange2(x, y) && hx == x && hy == y) {
      return false;
    }
  }
  return true;
}

int main() {
  cin >> H >> W;

  for (int i = 0; i < 4; ++i) {
    Dy[i] = -Dy[i];
    for (int j = 0; j < 4; ++j) {
      dhy[i][j] = -dhy[i][j];
    }
  }

  int sx = -1, sy = -1, sd = -1;
  int gx = -1, gy = -1;
  for (int y = 0; y < H; ++y) {
    string str;
    cin >> str;
    for (int x = 0; x < W; ++x) {
      switch (str[x]) {
      case '#':
        wall[y][x] = true;
        break;
      case 'G':
        gx = x, gy = y;
        break;
      case '^':
        sx = x, sy = y;
        sd = 0;
        break;
      case '>':
        sx = x, sy = y;
        sd = 1;
        break;
      case 'v':
        sx = x, sy = y;
        sd = 2;
        break;
      case '<':
        sx = x, sy = y;
        sd = 3;
        break;
      }
    }
  }
  int ans = -1;
  queue<Node> Q;
  //	fill(used[0], used[50], false);
  //	fill(reach[0][0][0][0], reach[49][49][50][51], false);
  Q.push((Node){sx, sy, sx + Dx[(sd + 1) % 4], sy + Dy[(sd + 1) % 4], sd});
  while (!Q.empty()) {
    Node node = Q.front();
    Q.pop();
    int px = node.x, py = node.y, hx = node.hx, hy = node.hy, dir = node.dir;
    if (!inRange(px, py))
      continue;
    if (wall[py][px])
      continue;
    if (!inRange2(hx, hy))
      continue;
    if (reach[py][px][hy + 1][hx + 1][dir])
      continue;
    if (isInvalidHand(px, py, hx, hy, dir))
      continue;
    reach[py][px][hy + 1][hx + 1][dir] = true;
    used[py][px] = true;
    if (px == gx && py == gy) {
      break;
    }
    //			cout << px << " " << py << " " << hx << " " << hy << " " << dir <<
    //endl;

    // move player
    {
      int npx = px + Dx[dir];
      int npy = py + Dy[dir];
      Q.push((Node){npx, npy, hx, hy, dir});
    }

    // move hand
    for (int dx = -1; dx <= 1; ++dx)
      for (int dy = -1; dy <= 1; ++dy) {
        int nhx = hx + dx;
        int nhy = hy + dy;
        if (inRange2(nhx, nhy) && Wall(hx, hy)) {
          Q.push((Node){px, py, nhx, nhy, dir});
        }
      }

    // change dir / turn
    Q.push((Node){px, py, hx, hy, (dir + 1) % 4});
    Q.push((Node){px, py, hx, hy, (dir - 1 + 4) % 4});
  }
  int s = 0;
  for (int y = 0; y < H; ++y) {
    for (int x = 0; x < W; ++x) {
      s += used[y][x];
    }
  }
  if (used[gy][gx] && (ans < 0 || s < ans)) {
    ans = s;
  }
  cout << ans << endl;
}

Fixed submission:
#include <bits/stdc++.h>

using namespace std;

int Dx[4] = {0, 1, 0, -1};
int Dy[4] = {1, 0, -1, 0};

int dhx[4][4] = {
    {0, 1, 1, 1},
    {1, 1, 0, -1},
    {0, -1, -1, -1},
    {-1, -1, 0, 1},
};
int dhy[4][4] = {
    {1, 1, 0, -1},
    {0, -1, -1, -1},
    {-1, -1, 0, 1},
    {0, 1, 1, 1},
};

struct Node {
  int x, y, hx, hy, dir;
};

int H, W;
int wall[60][60] = {0};
bool used[60][60] = {0};
bool reach[60][60][60][60][4] = {0};
bool inRange(int x, int y) { return 0 <= x && x < W && 0 <= y && y < H; }
bool inRange2(int x, int y) { return -1 <= x && x <= W && -1 <= y && y <= H; }
bool Wall(int x, int y) {
  if (inRange(x, y))
    return wall[y][x];
  return true;
}
bool isInvalidHand(int px, int py, int hx, int hy, int dir) {
  //	cout << ":" << px << " " << py << " " << hx << " " << hy << endl;
  if (!Wall(hx, hy))
    return true;
  for (int i = 0; i < 4; ++i) {
    int x = px + dhx[dir][i];
    int y = py + dhy[dir][i];
    if (inRange2(x, y) && hx == x && hy == y) {
      return false;
    }
  }
  return true;
}

int main() {
  cin >> H >> W;

  for (int i = 0; i < 4; ++i) {
    Dy[i] = -Dy[i];
    for (int j = 0; j < 4; ++j) {
      dhy[i][j] = -dhy[i][j];
    }
  }

  int sx = -1, sy = -1, sd = -1;
  int gx = -1, gy = -1;
  for (int y = 0; y < H; ++y) {
    string str;
    cin >> str;
    for (int x = 0; x < W; ++x) {
      switch (str[x]) {
      case '#':
        wall[y][x] = true;
        break;
      case 'G':
        gx = x, gy = y;
        break;
      case '^':
        sx = x, sy = y;
        sd = 0;
        break;
      case '>':
        sx = x, sy = y;
        sd = 1;
        break;
      case 'v':
        sx = x, sy = y;
        sd = 2;
        break;
      case '<':
        sx = x, sy = y;
        sd = 3;
        break;
      }
    }
  }
  int ans = -1;
  queue<Node> Q;
  //	fill(used[0], used[50], false);
  //	fill(reach[0][0][0][0], reach[49][49][50][51], false);
  Q.push((Node){sx, sy, sx + Dx[(sd + 1) % 4], sy + Dy[(sd + 1) % 4], sd});
  while (!Q.empty()) {
    Node node = Q.front();
    Q.pop();
    int px = node.x, py = node.y, hx = node.hx, hy = node.hy, dir = node.dir;
    if (!inRange(px, py))
      continue;
    if (wall[py][px])
      continue;
    if (!inRange2(hx, hy))
      continue;
    if (reach[py][px][hy + 1][hx + 1][dir])
      continue;
    if (isInvalidHand(px, py, hx, hy, dir))
      continue;
    reach[py][px][hy + 1][hx + 1][dir] = true;
    used[py][px] = true;
    if (px == gx && py == gy) {
      break;
    }
    //			cout << px << " " << py << " " << hx << " " << hy << " " << dir <<
    //endl;

    // move player
    {
      int npx = px + Dx[dir];
      int npy = py + Dy[dir];
      Q.push((Node){npx, npy, hx, hy, dir});
    }

    // move hand
    for (int dx = -1; dx <= 1; ++dx)
      for (int dy = -1; dy <= 1; ++dy) {
        int nhx = hx + dx;
        int nhy = hy + dy;
        if (inRange2(nhx, nhy) && Wall(hx, hy)) {
          Q.push((Node){px, py, nhx, nhy, dir});
        }
      }

    // change dir / turn
    Q.push((Node){px, py, hx, hy, (dir + 1) % 4});
    Q.push((Node){px, py, hx, hy, (dir - 1 + 4) % 4});
  }
  int s = 0;
  for (int y = 0; y < H; ++y) {
    for (int x = 0; x < W; ++x) {
      s += used[y][x];
    }
  }
  if (used[gy][gx] && (ans < 0 || s < ans)) {
    ans = s;
  }
  cout << ans << endl;
}