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

#include <cmath>
#include <cstdio>
#include <cstring>

using namespace std;

int W, H;

char map[16][16];
char g[16][16];
bool v[16][16];

int maxIce[128];
int ice[128];

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

int ans;
int px, py;
int sx, sy, gx, gy;

bool getMin(int ty, int tx, int turn) {

  if (turn + abs(ty - gy) + abs(tx - gx) >= ans) {
    return (false);
  }

  if (ty == gy && tx == gx) {
    ans = turn;
    return (true);
  }

  for (int i = 0; i < 4; i++) {
    int mx = tx + dx[i], my = ty + dy[i];
    if (0 <= mx && mx < W && 0 <= my && my < H && px != mx && py != my &&
        v[my][mx]) {
      return (false);
    }
  }

  for (int i = 0; i < 4; i++) {
    int mx = tx + dx[i], my = ty + dy[i];
    px = tx, py = ty;
    if (0 <= mx && mx < W && 0 <= my && my < H && map[my][mx] != '#' &&
        !v[my][mx]) {
      if (g[my][mx] == -1) {
        v[my][mx] = true;
        if (getMin(my, mx, turn + 1))
          return (true);
        v[my][mx] = false;
      } else if (maxIce[g[my][mx]] >= ice[g[my][mx]] + 1) {
        ice[g[my][mx]]++;
        v[my][mx] = true;
        if (getMin(my, mx, turn + 1))
          return (true);
        v[my][mx] = false;
        ice[g[my][mx]]--;
      }
    }
  }

  return (false);
}

void label(int ty, int tx, int p) {
  g[ty][tx] = p;
  maxIce[p]++;

  for (int i = 0; i < 4; i++) {
    int mx = tx + dx[i], my = ty + dy[i];

    if (0 <= mx && mx < W && 0 <= my && my < H && map[my][mx] == 'X' &&
        g[my][mx] == -1) {
      label(my, mx, p);
    }
  }
}

int main() {
  int idx;

  while (1) {
    scanf("%d %d", &W, &H);

    if (W + H == 0) {
      break;
    }

    for (int i = 0; i < H; i++) {
      scanf("%s", map[i]);
      for (int j = 0; j < W; j++) {
        if (map[i][j] == 'S') {
          map[i][j] = '.';
          sx = j, sy = i;
        }
        if (map[i][j] == 'G') {
          map[i][j] = '.';
          gx = j, gy = i;
        }
      }
    }

    memset(g, -1, sizeof(g));
    memset(maxIce, 0, sizeof(maxIce));

    idx = 0;
    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        if (map[i][j] == 'X' && g[i][j] == -1) {
          label(i, j, idx);
          maxIce[idx++] /= 2;
        }
      }
    }

    memset(ice, 0, sizeof(ice));
    memset(v, 0, sizeof(v));
    px = py = -1;
    v[sy][sx] = true;

    ans = 0;
    while (!getMin(sy, sx, 0)) {
      memset(ice, 0, sizeof(ice));
      memset(v, 0, sizeof(v));
      px = py = -1;
      v[sy][sx] = true;
      ans++;
    }

    printf("%d\\n", ans);
  }

  return (0);
}

Error: TLE

Fixed submission:

#include <cmath>
#include <cstdio>
#include <cstring>

using namespace std;

int ans;
int W, H;

char map[16][16];
char g[16][16];
bool v[16][16];

int maxIce[128];
int ice[128];

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

int px, py;
int sx, sy, gx, gy;

void getMin(int ty, int tx, int turn) {

  if (turn + abs(ty - gy) + abs(tx - gx) >= ans) {
    return;
  }

  if (ty == gy && tx == gx) {
    ans = turn;
    return;
  }

  for (int i = 0; i < 4; i++) {
    int mx = tx + dx[i], my = ty + dy[i];
    if (0 <= mx && mx < W && 0 <= my && my < H && px != mx && py != my &&
        v[my][mx]) {
      return;
    }
  }

  for (int i = 0; i < 4; i++) {
    int mx = tx + dx[i], my = ty + dy[i];
    px = tx, py = ty;
    if (0 <= mx && mx < W && 0 <= my && my < H && map[my][mx] != '#' &&
        !v[my][mx]) {
      if (g[my][mx] == -1) {
        v[my][mx] = true;
        getMin(my, mx, turn + 1);
        v[my][mx] = false;
      } else if (maxIce[g[my][mx]] >= ice[g[my][mx]] + 1) {
        ice[g[my][mx]]++;
        v[my][mx] = true;
        getMin(my, mx, turn + 1);
        v[my][mx] = false;
        ice[g[my][mx]]--;
      }
    }
  }
}

void label(int ty, int tx, int p) {
  g[ty][tx] = p;
  maxIce[p]++;

  for (int i = 0; i < 4; i++) {
    int mx = tx + dx[i], my = ty + dy[i];

    if (0 <= mx && mx < W && 0 <= my && my < H && map[my][mx] == 'X' &&
        g[my][mx] == -1) {
      label(my, mx, p);
    }
  }
}

int main() {
  int idx;

  while (1) {
    scanf("%d %d", &W, &H);

    if (W + H == 0) {
      break;
    }

    for (int i = 0; i < H; i++) {
      scanf("%s", map[i]);
      for (int j = 0; j < W; j++) {
        if (map[i][j] == 'S') {
          map[i][j] = '.';
          sx = j, sy = i;
        }
        if (map[i][j] == 'G') {
          map[i][j] = '.';
          gx = j, gy = i;
        }
      }
    }

    memset(g, -1, sizeof(g));
    memset(maxIce, 0, sizeof(maxIce));

    idx = 0;
    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        if (map[i][j] == 'X' && g[i][j] == -1) {
          label(i, j, idx);
          maxIce[idx++] /= 2;
        }
      }
    }

    memset(ice, 0, sizeof(ice));
    memset(v, 0, sizeof(v));
    px = py = -1;
    v[sy][sx] = true;
    ans = W * H;
    getMin(sy, sx, 0);

    printf("%d\\n", ans);
  }

  return (0);
}