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

#include <cassert>
#include <iostream>
#include <queue>
#include <tuple>
#include <vector>

using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef tuple<int, int, int> PD;
typedef long double ld;

const int MN = 550;
const int INT_INF = 1 << 28;
const int d4[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

int w, h;
string g[MN];
int dist2g[MN][MN];
int dist2b[MN][MN];

bool bc(int x, int y) { return (0 <= x && x < w && 0 <= y && y < h); }

void init2g() {
  queue<PD> q;
  for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
      dist2g[y][x] = INT_INF;
      if (g[y][x] == 'g') {
        q.push(PD(x, y, 0));
      }
    }
  }
  while (!q.empty()) {
    int x, y, d;
    tie(x, y, d) = q.front();
    q.pop();
    //  assert(g[y][x] != '#');
    if (dist2g[y][x] < INT_INF)
      continue;
    dist2g[y][x] = d;
    for (int i = 0; i < 4; i++) {
      int nx = x + d4[i][0], ny = y + d4[i][1];
      if (!bc(nx, ny))
        continue;
      if (g[ny][nx] == '#' || g[ny][nx] == '*')
        continue;
      q.push(PD(nx, ny, d + 1));
    }
  }
}

void init2b() {
  queue<PD> q;
  for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
      dist2b[y][x] = INT_INF;
      if (g[y][x] == '*') {
        q.push(PD(x, y, 0));
      }
    }
  }
  while (!q.empty()) {
    int x, y, d;
    tie(x, y, d) = q.front();
    q.pop();
    if (dist2b[y][x] < INT_INF)
      continue;
    //  assert(g[y][x] != '#');
    dist2b[y][x] = d;
    for (int i = 0; i < 4; i++) {
      int nx = x + d4[i][0], ny = y + d4[i][1];
      if (!bc(nx, ny))
        continue;
      if (g[ny][nx] == '#')
        continue;
      q.push(PD(nx, ny, d + 1));
    }
  }
}

int main() {
  cin >> w >> h;
  for (int i = 0; i < h; i++) {
    cin >> g[i];
  }
  int pc = 0;
  for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
      if (g[y][x] == '#')
        continue;
      if (g[y][x] == '*')
        continue;
      if (g[y][x] == 'g')
        continue;
      pc++;
    }
  }
  init2g();
  init2b();
  /*
  printf("pc %d\\n", pc);
  for (int y = 0; y < h; y++) {
      for (int x = 0; x < w; x++) {
          if (dist2g[y][x] == INT_INF) {
              printf("-1 ");
          } else {
              printf("%2d ", dist2g[y][x]);
          }
      } printf("\\n");
  }
  printf("end\\n");
  for (int y = 0; y < h; y++) {
      for (int x = 0; x < w; x++) {
          if (dist2b[y][x] == INT_INF) {
              printf("-1 ");
          } else {
              printf("%2d ", dist2b[y][x]);
          }
      } printf("\\n");
  }
  printf("end\\n");*/
  int sx, sy;
  for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
      if (g[y][x] == 's') {
        sx = x;
        sy = y;
      }
    }
  }
  if (dist2b[sy][sx] == INT_INF) {
    assert(dist2g[sy][sx] < INT_INF);
    printf("%d\\n", dist2g[sy][sx]);
    return 0;
  }
  ld l = 0, r = 1e20;
  for (int i = 0; i < 200; i++) {
    // printf("%Lf %Lf\\n", l, r);
    ld md = (l + r) / 2;
    ld e = 0;
    for (int y = 0; y < h; y++) {
      for (int x = 0; x < w; x++) {
        if (g[y][x] == '#')
          continue;
        if (g[y][x] == '*')
          continue;
        if (g[y][x] == 'g')
          continue;
        if (dist2g[y][x] == INT_INF) {
          e += dist2b[y][x] + md;
          continue;
        }

        e += min<ld>(dist2g[y][x], dist2b[y][x] + md);
      }
    }
    e /= pc;
    // printf("emd %Lf %Lf\\n", e, md);
    if (e > md) {
      l = md;
    } else {
      r = md;
    }
  }
  if (dist2g[sy][sx] == INT_INF) {
    printf("%.20Lf\\n", dist2b[sy][sx] + l);
    return 0;
  }
  printf("%.20Lf\\n", min<ld>(dist2g[sy][sx], dist2b[sy][sx] + l));
  return 0;
}

Error: TLE

Fixed submission:

#include <cassert>
#include <iostream>
#include <queue>
#include <tuple>
#include <vector>

using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef tuple<int, int, int> PD;
typedef long double ld;

const int MN = 550;
const int INT_INF = 1 << 28;
const int d4[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

int w, h;
string g[MN];
int dist2g[MN][MN];
int dist2b[MN][MN];

bool bc(int x, int y) { return (0 <= x && x < w && 0 <= y && y < h); }

void init2g() {
  queue<PD> q;
  for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
      dist2g[y][x] = INT_INF;
      if (g[y][x] == 'g') {
        q.push(PD(x, y, 0));
      }
    }
  }
  while (!q.empty()) {
    int x, y, d;
    tie(x, y, d) = q.front();
    q.pop();
    //  assert(g[y][x] != '#');
    if (dist2g[y][x] < INT_INF)
      continue;
    dist2g[y][x] = d;
    for (int i = 0; i < 4; i++) {
      int nx = x + d4[i][0], ny = y + d4[i][1];
      if (!bc(nx, ny))
        continue;
      if (g[ny][nx] == '#' || g[ny][nx] == '*')
        continue;
      q.push(PD(nx, ny, d + 1));
    }
  }
}

void init2b() {
  queue<PD> q;
  for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
      dist2b[y][x] = INT_INF;
      if (g[y][x] == '*') {
        q.push(PD(x, y, 0));
      }
    }
  }
  while (!q.empty()) {
    int x, y, d;
    tie(x, y, d) = q.front();
    q.pop();
    if (dist2b[y][x] < INT_INF)
      continue;
    //  assert(g[y][x] != '#');
    dist2b[y][x] = d;
    for (int i = 0; i < 4; i++) {
      int nx = x + d4[i][0], ny = y + d4[i][1];
      if (!bc(nx, ny))
        continue;
      if (g[ny][nx] == '#')
        continue;
      q.push(PD(nx, ny, d + 1));
    }
  }
}

int main() {
  cin >> w >> h;
  for (int i = 0; i < h; i++) {
    cin >> g[i];
  }
  int pc = 0;
  for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
      if (g[y][x] == '#')
        continue;
      if (g[y][x] == '*')
        continue;
      if (g[y][x] == 'g')
        continue;
      pc++;
    }
  }
  init2g();
  init2b();
  /*
  printf("pc %d\\n", pc);
  for (int y = 0; y < h; y++) {
      for (int x = 0; x < w; x++) {
          if (dist2g[y][x] == INT_INF) {
              printf("-1 ");
          } else {
              printf("%2d ", dist2g[y][x]);
          }
      } printf("\\n");
  }
  printf("end\\n");
  for (int y = 0; y < h; y++) {
      for (int x = 0; x < w; x++) {
          if (dist2b[y][x] == INT_INF) {
              printf("-1 ");
          } else {
              printf("%2d ", dist2b[y][x]);
          }
      } printf("\\n");
  }
  printf("end\\n");*/
  int sx, sy;
  for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
      if (g[y][x] == 's') {
        sx = x;
        sy = y;
      }
    }
  }
  if (dist2b[sy][sx] == INT_INF) {
    assert(dist2g[sy][sx] < INT_INF);
    printf("%d\\n", dist2g[sy][sx]);
    return 0;
  }
  ld l = 0, r = 1e15;
  while (r - l > 1e-10) {
    // printf("%Lf %Lf\\n", l, r);
    ld md = (l + r) / 2;
    ld e = 0;
    for (int y = 0; y < h; y++) {
      for (int x = 0; x < w; x++) {
        if (g[y][x] == '#')
          continue;
        if (g[y][x] == '*')
          continue;
        if (g[y][x] == 'g')
          continue;
        if (dist2g[y][x] == INT_INF) {
          e += dist2b[y][x] + md;
          continue;
        }

        e += min<ld>(dist2g[y][x], dist2b[y][x] + md);
      }
    }
    e /= pc;
    // printf("emd %Lf %Lf\\n", e, md);
    if (e > md) {
      l = md;
    } else {
      r = md;
    }
  }
  printf("%.20Lf\\n", min<ld>(dist2g[sy][sx], dist2b[sy][sx] + l));
  return 0;
}