Problem p00247 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

const int MAXH = 13;
const int MAXW = 13;
const int di[] = {0, 1, 0, -1};
const int dj[] = {1, 0, -1, 0};
const int INF = 1 << 28;

int W, H;
char G[MAXH][MAXW];
int si, sj, ti, tj;
int N;
int ice[MAXH][MAXW];
int ans;
bool vis[MAXH][MAXW];
int cnt[1000];
int fromG[MAXH][MAXW];

int dfs(int pi, int pj, int n) {
  int res = 1;
  ice[pi][pj] = n;
  for (int k = 0; k < 4; ++k) {
    int ni = pi + di[k];
    int nj = pj + dj[k];
    if (ni < 0 || ni >= H)
      continue;
    if (nj < 0 || nj >= W)
      continue;
    if (G[ni][nj] != 'X')
      continue;
    if (ice[ni][nj] != -1)
      continue;
    res += dfs(ni, nj, n);
  }
  return res;
}

void bfs(int si, int sj) {
  queue<pair<int, int>> que;
  fill(fromG[0], fromG[MAXH], INF);
  que.push(make_pair(si, sj));
  fromG[si][sj] = 0;
  while (que.size()) {
    int pi = que.front().first;
    int pj = que.front().second;
    que.pop();
    for (int k = 0; k < 4; ++k) {
      int ni = pi + di[k];
      int nj = pj + dj[k];
      if (ni < 0 || ni >= H)
        continue;
      if (nj < 0 || nj >= W)
        continue;
      if (G[ni][nj] == '#')
        continue;
      if (fromG[ni][nj] != INF)
        continue;
      que.push(make_pair(ni, nj));
      fromG[ni][nj] = fromG[pi][pj] + 1;
    }
  }
}

void dfs2(int pi, int pj, int previ, int prevj, int cost) {
  if (cost + fromG[pi][pj] >= ans)
    return;
  if (pi == ti && pj == tj) {
    ans = min(ans, cost);
    return;
  }
  for (int k = 0; k < 4; ++k) {
    int ni = pi + di[k];
    int nj = pj + dj[k];
    if (ni < 0 || ni >= H)
      continue;
    if (nj < 0 || nj >= W)
      continue;
    if (ni == previ && nj == prevj)
      continue;
    if (vis[ni][nj])
      return;
  }

  vis[pi][pj] = true;
  for (int k = 0; k < 4; ++k) {
    int ni = pi + di[k];
    int nj = pj + dj[k];
    if (ni < 0 || ni >= H)
      continue;
    if (nj < 0 || nj >= W)
      continue;
    if (vis[ni][nj])
      continue;
    if (G[ni][nj] == '#')
      continue;
    if (G[ni][nj] == 'X' && cnt[ice[ni][nj]] == 0)
      continue;

    if (G[ni][nj] == 'X')
      cnt[ice[ni][nj]] -= 1;
    dfs2(ni, nj, pi, pj, cost + 1);
    if (G[ni][nj] == 'X')
      cnt[ice[ni][nj]] += 1;
  }
  vis[pi][pj] = false;
}

int main() {
  while (cin >> W >> H && (W | H)) {
    for (int i = 0; i < H; ++i) {
      for (int j = 0; j < W; ++j) {
        cin >> G[i][j];
        if (G[i][j] == 'S') {
          si = i;
          sj = j;
          G[i][j] = '.';
        }
        if (G[i][j] == 'G') {
          ti = i;
          tj = j;
          G[i][j] = '.';
        }
      }
    }
    fill(ice[0], ice[MAXH], -1);
    N = 0;
    for (int i = 0; i < H; ++i) {
      for (int j = 0; j < W; ++j) {
        if (G[i][j] == 'X' && ice[i][j] == -1) {
          cnt[N] = dfs(i, j, N) / 2;
          if (cnt[N] == 0) {
            ice[i][j] = -1;
            G[i][j] = '#';
          } else {
            ++N;
          }
        }
      }
    }
    bfs(ti, tj);
    ans = INF;
    fill(vis[0], vis[MAXH], 0);
    dfs2(si, sj, -1, -1, 0);
    cout << ans << endl;
  }
  return 0;
}

Fixed submission:
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

const int MAXH = 13;
const int MAXW = 13;
const int di[] = {1, 0, -1, 0};
const int dj[] = {0, 1, 0, -1};
const int INF = 1 << 28;

int W, H;
char G[MAXH][MAXW];
int si, sj, ti, tj;
int N;
int ice[MAXH][MAXW];
int ans;
bool vis[MAXH][MAXW];
int cnt[1000];
int fromG[MAXH][MAXW];

int dfs(int pi, int pj, int n) {
  int res = 1;
  ice[pi][pj] = n;
  for (int k = 0; k < 4; ++k) {
    int ni = pi + di[k];
    int nj = pj + dj[k];
    if (ni < 0 || ni >= H)
      continue;
    if (nj < 0 || nj >= W)
      continue;
    if (G[ni][nj] != 'X')
      continue;
    if (ice[ni][nj] != -1)
      continue;
    res += dfs(ni, nj, n);
  }
  return res;
}

void bfs(int si, int sj) {
  queue<pair<int, int>> que;
  fill(fromG[0], fromG[MAXH], INF);
  que.push(make_pair(si, sj));
  fromG[si][sj] = 0;
  while (que.size()) {
    int pi = que.front().first;
    int pj = que.front().second;
    que.pop();
    for (int k = 0; k < 4; ++k) {
      int ni = pi + di[k];
      int nj = pj + dj[k];
      if (ni < 0 || ni >= H)
        continue;
      if (nj < 0 || nj >= W)
        continue;
      if (G[ni][nj] == '#')
        continue;
      if (fromG[ni][nj] != INF)
        continue;
      que.push(make_pair(ni, nj));
      fromG[ni][nj] = fromG[pi][pj] + 1;
    }
  }
}

void dfs2(int pi, int pj, int previ, int prevj, int cost) {
  if (cost + fromG[pi][pj] >= ans)
    return;
  if (pi == ti && pj == tj) {
    ans = min(ans, cost);
    return;
  }
  for (int k = 0; k < 4; ++k) {
    int ni = pi + di[k];
    int nj = pj + dj[k];
    if (ni < 0 || ni >= H)
      continue;
    if (nj < 0 || nj >= W)
      continue;
    if (ni == previ && nj == prevj)
      continue;
    if (vis[ni][nj])
      return;
  }

  vis[pi][pj] = true;
  for (int k = 0; k < 4; ++k) {
    int ni = pi + di[k];
    int nj = pj + dj[k];
    if (ni < 0 || ni >= H)
      continue;
    if (nj < 0 || nj >= W)
      continue;
    if (vis[ni][nj])
      continue;
    if (G[ni][nj] == '#')
      continue;
    if (G[ni][nj] == 'X' && cnt[ice[ni][nj]] == 0)
      continue;

    if (G[ni][nj] == 'X')
      cnt[ice[ni][nj]] -= 1;
    dfs2(ni, nj, pi, pj, cost + 1);
    if (G[ni][nj] == 'X')
      cnt[ice[ni][nj]] += 1;
  }
  vis[pi][pj] = false;
}

int main() {
  while (cin >> W >> H && (W | H)) {
    for (int i = 0; i < H; ++i) {
      for (int j = 0; j < W; ++j) {
        cin >> G[i][j];
        if (G[i][j] == 'S') {
          si = i;
          sj = j;
          G[i][j] = '.';
        }
        if (G[i][j] == 'G') {
          ti = i;
          tj = j;
          G[i][j] = '.';
        }
      }
    }
    fill(ice[0], ice[MAXH], -1);
    N = 0;
    for (int i = 0; i < H; ++i) {
      for (int j = 0; j < W; ++j) {
        if (G[i][j] == 'X' && ice[i][j] == -1) {
          cnt[N] = dfs(i, j, N) / 2;
          if (cnt[N] == 0) {
            ice[i][j] = -1;
            G[i][j] = '#';
          } else {
            ++N;
          }
        }
      }
    }
    bfs(ti, tj);
    ans = INF;
    fill(vis[0], vis[MAXH], 0);
    dfs2(si, sj, -1, -1, 0);
    cout << ans << endl;
  }
  return 0;
}