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

#include <algorithm>
#include <iostream>
#include <queue>
#include <unordered_set>
#include <vector>

using namespace std;

typedef long long ll;
typedef unsigned char uchar;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> pii;

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

int h, w;
char field[16][16];
int label[16][16];

const int dy[] = {-1, 0, 1, 0};
const int dx[] = {0, -1, 0, 1};

int labeling(int y, int x, int l) {
  int ret = 1;
  label[y][x] = l;

  rep(i, 4) {
    int py = y + dy[i];
    int px = x + dx[i];
    if (py < 0 || h <= py || px < 0 || w <= px)
      continue;
    if (field[py][px] == 'X' && label[py][px] == 0) {
      ret += labeling(py, px, l);
    }
  }

  return ret;
}

struct Data {
  int y, x, cost;
  vector<uchar> broken;

  bool operator==(const Data &d) const {
    return y == d.y && x == d.x && broken == d.broken;
  }
};

struct myhash {
  size_t operator()(const Data &d) const {
    size_t h = d.y ^ d.x;
    rep(i, d.broken.size()) h ^= d.broken[i] << i;
    return h;
  }
};

int func() {
  rep(i, h) rep(j, w) label[i][j] = 0;

  rep(i, h) { cin >> field[i]; }

  vector<uchar> area;
  rep(y, h) rep(x, w) {
    if (field[y][x] == 'X' && label[y][x] == 0) {
      area.push_back(labeling(y, x, area.size() + 1));
    }
  }

  for (uchar &a : area) {
    a /= 2;
  }

  queue<Data> Q;
  unordered_set<Data, myhash> visited;

  rep(y, h) rep(x, w) {
    if (field[y][x] == 'S') {
      Q.push({y, x, 0, area});
      visited.insert(Q.front());
    }
  }

  while (!Q.empty()) {
    Data d = Q.front();
    Q.pop();

    rep(i, 4) {
      int py = d.y + dy[i];
      int px = d.x + dx[i];
      if (py < 0 || h <= py || px < 0 || w <= px || field[py][px] == '#')
        continue;

      Data next;
      if (field[py][px] == 'G') {
        return d.cost + 1;
      } else if (field[py][px] == 'X') {
        uchar &b = d.broken[label[py][px] - 1];
        if (b == 0)
          continue;
        --b;
        next = {py, px, d.cost + 1, d.broken};
        ++b;
      } else {
        next = {py, px, d.cost + 1, d.broken};
      }

      if (visited.count(next))
        continue;

      Q.push(next);
      visited.insert(next);
    }
  }

  return 0;
}

int main() {
  while (cin >> w >> h, w) {
    printf("%d\\n", func());
  }
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <queue>
#include <unordered_set>
#include <vector>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> pii;

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

int h, w;
char field[16][16];
int label[16][16];

const int dy[] = {-1, 0, 1, 0};
const int dx[] = {0, -1, 0, 1};

int labeling(int y, int x, int l) {
  int ret = 1;
  label[y][x] = l;

  rep(i, 4) {
    int py = y + dy[i];
    int px = x + dx[i];
    if (py < 0 || h <= py || px < 0 || w <= px)
      continue;
    if (field[py][px] == 'X' && label[py][px] == 0) {
      ret += labeling(py, px, l);
    }
  }

  return ret;
}

struct Data {
  int y, x, cost;
  vi broken;

  bool operator==(const Data &d) const {
    return y == d.y && x == d.x && broken == d.broken;
  }
};

struct myhash {
  size_t operator()(const Data &d) const {
    size_t h = d.y ^ d.x;
    rep(i, d.broken.size()) h ^= d.broken[i] << i;
    return h;
  }
};

int func() {
  rep(i, h) rep(j, w) label[i][j] = 0;

  rep(i, h) { cin >> field[i]; }

  vi area;
  rep(y, h) rep(x, w) {
    if (field[y][x] == 'X' && label[y][x] == 0) {
      area.push_back(labeling(y, x, area.size() + 1));
    }
  }

  for (int &a : area) {
    a /= 2;
  }

  queue<Data> Q;
  unordered_set<Data, myhash> visited;

  rep(y, h) rep(x, w) {
    if (field[y][x] == 'S') {
      Q.push({y, x, 0, area});
      visited.insert(Q.front());
    }
  }

  while (!Q.empty()) {
    Data d = Q.front();
    Q.pop();

    rep(i, 4) {
      int py = d.y + dy[i];
      int px = d.x + dx[i];
      if (py < 0 || h <= py || px < 0 || w <= px || field[py][px] == '#')
        continue;

      Data next;
      if (field[py][px] == 'G') {
        return d.cost + 1;
      } else if (field[py][px] == 'X') {
        int &b = d.broken[label[py][px] - 1];
        if (b == 0)
          continue;
        --b;
        next = {py, px, d.cost + 1, d.broken};
        ++b;
      } else {
        next = {py, px, d.cost + 1, d.broken};
      }

      if (visited.count(next))
        continue;

      Q.push(next);
      visited.insert(next);
    }
  }

  return 0;
}

int main() {
  while (cin >> w >> h, w) {
    printf("%d\\n", func());
  }
}