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

#include <algorithm>
#include <iostream>
#include <map>
#include <tuple>
#include <vector>
using namespace std;

enum { FLOOR = -3, WALL, ICE };

enum { Y, X };
const int NEXT[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

const int NIL = -1;
const int INF = 1000000000;

int h, w;
vector<vector<int>> field;
vector<int> durability;
int sy, sx, gy, gx;
vector<vector<int>> visited;

int flood_fill(int y, int x, int id) {
  int result = 1;
  field[y][x] = id;
  for (const auto &d : NEXT) {
    int ny = y + d[Y];
    int nx = x + d[X];
    if (field[ny][nx] != ICE)
      continue;
    result += flood_fill(ny, nx, id);
  }
  return result;
}

int dfs(int y, int x, int step) {
  if (y == gy && x == gx)
    return step;
  if (step == 0)
    return NIL;
  if (abs(y - gy) + abs(x - gx) > step)
    return NIL;  // 枝刈り１
  int count = 0; // 枝刈り４
  for (const auto &d : NEXT)
    if (visited[y + d[Y]][x + d[X]])
      ++count; //
  if (count >= 2)
    return NIL; //
  int result = NIL;
  for (const auto &d : NEXT) {
    int ny = y + d[Y];
    int nx = x + d[X];
    if (field[ny][nx] == WALL)
      continue;
    if (field[ny][nx] == FLOOR) {
      if (visited[ny][nx])
        continue;
      visited[ny][nx] = 1;
      result = max(result, dfs(ny, nx, step - 1));
      visited[ny][nx] = 0;
    } else {
      if (durability[field[ny][nx]] <= 0)
        continue;
      if (visited[ny][nx])
        continue;
      visited[ny][nx] = 1;
      --durability[field[ny][nx]];
      result = max(result, dfs(ny, nx, step - 1));
      ++durability[field[ny][nx]];
      visited[ny][nx] = 0;
    }
  }
  return result;
}

int solve() {
  visited = vector<vector<int>>(h + 2, vector<int>(w + 2, 0));
  for (int i = 1; i <= INF; ++i) {
    int result = dfs(sy, sx, i);
    if (result != NIL)
      return i - result;
  }
  return NIL;
}

int main() {
  while (cin >> w >> h, w | h) {
    field = vector<vector<int>>(h + 2, vector<int>(w + 2, WALL));
    for (int i = 1; i <= h; ++i)
      for (int j = 1; j <= w; ++j) {
        char c;
        cin >> c;
        if (c == '#')
          field[i][j] = WALL;
        else if (c == 'X')
          field[i][j] = ICE;
        else {
          field[i][j] = FLOOR;
          if (c == 'S') {
            sy = i;
            sx = j;
          }
          if (c == 'G') {
            gy = i;
            gx = j;
          }
        }
      }

    durability.clear();
    for (int i = 1; i <= h; ++i)
      for (int j = 1; j <= w; ++j)
        if (field[i][j] == ICE)
          durability.push_back(flood_fill(i, j, durability.size()) / 2);

    cout << solve() << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <map>
#include <tuple>
#include <vector>
using namespace std;

enum { FLOOR = -3, WALL, ICE };

enum { Y, X };
const int NEXT[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

const int NIL = -1;
const int INF = 1000000000;

int h, w;
vector<vector<int>> field;
vector<int> durability;
int sy, sx, gy, gx;
vector<vector<int>> visited;
int memo; // 枝刈り３

int flood_fill(int y, int x, int id) {
  int result = 1;
  field[y][x] = id;
  for (const auto &d : NEXT) {
    int ny = y + d[Y];
    int nx = x + d[X];
    if (field[ny][nx] != ICE)
      continue;
    result += flood_fill(ny, nx, id);
  }
  return result;
}

int dfs(int y, int x, int step) {
  if (y == gy && x == gx)
    return step;
  memo = min(memo, abs(y - gy) + abs(x - gx)); // 枝刈り３
  if (step == 0)
    return NIL;
  if (abs(y - gy) + abs(x - gx) > step)
    return NIL; // 枝刈り１
  int result = NIL;
  for (const auto &d : NEXT) {
    int ny = y + d[Y];
    int nx = x + d[X];
    if (field[ny][nx] == WALL)
      continue;
    if (field[ny][nx] == FLOOR) {
      if (visited[ny][nx])
        continue;
      visited[ny][nx] = 1;
      result = max(result, dfs(ny, nx, step - 1));
      visited[ny][nx] = 0;
    } else {
      if (durability[field[ny][nx]] <= 0)
        continue;
      if (visited[ny][nx])
        continue;
      visited[ny][nx] = 1;
      --durability[field[ny][nx]];
      result = max(result, dfs(ny, nx, step - 1));
      ++durability[field[ny][nx]];
      visited[ny][nx] = 0;
    }
  }
  return result;
}

int solve() {
  visited = vector<vector<int>>(h + 2, vector<int>(w + 2, 0));
  for (int i = 1; i <= INF; ++i) {
    memo = 1000000000; // 枝刈り３
    int result = dfs(sy, sx, i);
    if (result != NIL)
      return i - result;
    i += memo - 1;
  }
  return NIL;
}

int main() {
  while (cin >> w >> h, w | h) {
    field = vector<vector<int>>(h + 2, vector<int>(w + 2, WALL));
    for (int i = 1; i <= h; ++i)
      for (int j = 1; j <= w; ++j) {
        char c;
        cin >> c;
        if (c == '#')
          field[i][j] = WALL;
        else if (c == 'X')
          field[i][j] = ICE;
        else {
          field[i][j] = FLOOR;
          if (c == 'S') {
            sy = i;
            sx = j;
          }
          if (c == 'G') {
            gy = i;
            gx = j;
          }
        }
      }

    durability.clear();
    for (int i = 1; i <= h; ++i)
      for (int j = 1; j <= w; ++j)
        if (field[i][j] == ICE)
          durability.push_back(flood_fill(i, j, durability.size()) / 2);

    cout << solve() << endl;
  }
}