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

#include <algorithm>
#include <cassert>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <vector>
using namespace std;

#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define each(i, c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); i++)
#define pb push_back
#define mp make_pair
#define all(c) c.begin(), c.end()
#define dbg(x) cerr << __LINE__ << ": " << #x << " = " << (x) << endl

typedef vector<int> vi;
typedef pair<int, int> pi;
typedef long long ll;
const int inf = (int)1e9;
const double EPS = 1e-9, INF = 1e12;

const int dy[] = {-1, 0, 1, 0}, dx[] = {0, -1, 0, 1};
int p[200];
int root(int x) {
  if (p[x] < 0)
    return x;
  return p[x] = root(p[x]);
}
int h, w, dist[200][200];
int n, sz[200], to[200];
char in[12][13];

int main() {
  while (cin >> w >> h, h) {
    int sy, sx, gy, gx;
    rep(i, h * w) p[i] = -1;
    rep(i, 200) rep(j, 200) dist[i][j] = i == j ? 0 : inf;

    rep(i, h) {
      cin >> in[i];
      rep(j, w) {
        if (in[i][j] == 'S')
          sy = i, sx = j;
        if (in[i][j] == 'G')
          gy = i, gx = j;
        if (in[i][j] == 'X')
          rep(d, 2) {
            int ny = i + dy[d], nx = j + dx[d];
            if (ny >= 0 && nx >= 0 && in[ny][nx] == 'X') {
              int a = root(i * w + j), b = root(ny * w + nx);
              if (a != b) {
                p[a] += p[b];
                p[b] = a;
              }
            }
          }
      }
    }
    rep(i, h) rep(j, w) if (in[i][j] != '#') {
      rep(d, 4) {
        int ny = i + dy[d], nx = j + dx[d];
        if (ny < 0 || ny >= h || nx < 0 || nx >= w)
          continue;
        if (in[ny][nx] == '#')
          continue;
        dist[i * w + j][ny * w + nx] = 1;
      }
    }
    rep(k, 200) rep(i, 200) rep(j, 200) dist[i][j] =
        min(dist[i][j], dist[i][k] + dist[k][j]);

    priority_queue<pair<pi, pair<int, vi>>> q; // cost*, cost, pos, ice
    set<pair<int, vi>> s;

    n = 0;
    memset(to, -1, sizeof(to));
    rep(i, h) rep(j, w) if (in[i][j] == 'X') {
      int r = root(i * w + j);
      if (to[r] < 0) {
        sz[n] = -p[r];
        to[r] = n++;
      }
    }
    q.push(mp(mp(-dist[sy * w + sx][gy * w + gx], 0), mp(sy * w + sx, vi(n))));

    while (!q.empty()) {
      vi v = q.top().second.second;
      int cost = q.top().first.second;
      int y = q.top().second.first;
      int x = y % w;
      y /= w;
      q.pop();

      if (s.count(mp(y * w + x, v)))
        continue;
      s.insert(mp(y * w + x, v));

      if (in[y][x] == 'G') {
        cout << -cost << endl;
        break;
      }

      rep(d, 4) {
        int ny = y + dy[d], nx = x + dx[d];
        if (ny < 0 || nx < 0 || ny >= h || nx >= w)
          continue;
        if (in[ny][nx] == '#')
          continue;
        vi nv = v;

        if (in[ny][nx] == 'X') {
          int r = to[root(ny * w + nx)];
          nv[r]++;
          if (sz[r] < nv[r] * 2)
            continue;
        }

        if (!s.count(mp(ny * w + nx, nv)))
          q.push(mp(mp(cost - dist[ny * w + nx][gy * w + gx], cost - 1),
                    mp(ny * w + nx, nv)));
      }
    }
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <vector>
using namespace std;

#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define each(i, c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); i++)
#define pb push_back
#define mp make_pair
#define all(c) c.begin(), c.end()
#define dbg(x) cerr << __LINE__ << ": " << #x << " = " << (x) << endl

typedef vector<int> vi;
typedef pair<int, int> pi;
typedef long long ll;
const int inf = (int)1e9;
const double EPS = 1e-9, INF = 1e12;

const int dy[] = {-1, 0, 1, 0}, dx[] = {0, -1, 0, 1};
int p[200];
int root(int x) {
  if (p[x] < 0)
    return x;
  return p[x] = root(p[x]);
}
int h, w, dist[200][200];
int n, sz[200], to[200];
char in[12][13];

set<pair<int, vi>> s;

int main() {
  while (cin >> w >> h, h) {
    int sy, sx, gy, gx;
    rep(i, h * w) p[i] = -1;
    rep(i, h * w) rep(j, h * w) dist[i][j] = i == j ? 0 : inf;

    rep(i, h) {
      cin >> in[i];
      rep(j, w) {
        if (in[i][j] == 'S')
          sy = i, sx = j;
        if (in[i][j] == 'G')
          gy = i, gx = j;
        if (in[i][j] == 'X')
          rep(d, 2) {
            int ny = i + dy[d], nx = j + dx[d];
            if (ny >= 0 && nx >= 0 && in[ny][nx] == 'X') {
              int a = root(i * w + j), b = root(ny * w + nx);
              if (a != b) {
                p[a] += p[b];
                p[b] = a;
              }
            }
          }
      }
    }
    rep(i, h) rep(j, w) if (in[i][j] != '#') {
      rep(d, 4) {
        int ny = i + dy[d], nx = j + dx[d];
        if (ny < 0 || ny >= h || nx < 0 || nx >= w)
          continue;
        if (in[ny][nx] == '#')
          continue;
        dist[i * w + j][ny * w + nx] = 1;
      }
    }
    rep(k, 200) rep(i, 200) rep(j, 200) dist[i][j] =
        min(dist[i][j], dist[i][k] + dist[k][j]);

    priority_queue<pair<pi, pair<int, vi>>> q; // cost*, cost, pos, ice

    n = 0;
    memset(to, -1, sizeof(to));
    rep(i, h) rep(j, w) if (in[i][j] == 'X') {
      int r = root(i * w + j);
      if (to[r] < 0) {
        sz[n] = -p[r];
        to[r] = n++;
      }
    }
    s.clear();
    q.push(mp(mp(-dist[sy * w + sx][gy * w + gx], 0), mp(sy * w + sx, vi(n))));

    while (!q.empty()) {
      vi v = q.top().second.second;
      int cost = q.top().first.second;
      int y = q.top().second.first;
      int x = y % w;
      y /= w;
      q.pop();

      if (s.count(mp(y * w + x, v)))
        continue;
      s.insert(mp(y * w + x, v));

      if (in[y][x] == 'G') {
        cout << -cost << endl;
        break;
      }

      rep(d, 4) {
        int ny = y + dy[d], nx = x + dx[d];
        if (ny < 0 || nx < 0 || ny >= h || nx >= w)
          continue;
        if (in[ny][nx] == '#')
          continue;
        vi nv = v;

        if (in[ny][nx] == 'X') {
          int r = to[root(ny * w + nx)];
          nv[r]++;
          if (sz[r] < nv[r] * 2)
            continue;
        }

        if (!s.count(mp(ny * w + nx, nv)))
          q.push(mp(mp(cost - dist[ny * w + nx][gy * w + gx], cost - 1),
                    mp(ny * w + nx, nv)));
      }
    }
  }
  return 0;
}