Problem p01453 (C++) — buggy submission, verdict: Runtime Error

#include <cmath>
#include <cstdio>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <tuple>
#include <vector>
#define repeat(i, n) for (int i = 0; (i) < (n); ++(i))
template <class T> bool setmax(T &l, T const &r) {
  if (not(l < r))
    return false;
  l = r;
  return true;
}
template <class T> bool setmin(T &l, T const &r) {
  if (not(r < l))
    return false;
  l = r;
  return true;
}
using namespace std;
const int inf = 1e9 + 7;
const int dy[] = {-1, 1, 0, 0};
const int dx[] = {0, 0, 1, -1};
int main() {
  // input
  int w, h;
  cin >> w >> h;
  vector<string> c(h);
  repeat(y, h) cin >> c[y];
  // modify input
  int sy, sx, gy, gx;
  repeat(y, h) repeat(x, w) {
    if (c[y][x] == 's') {
      sy = y;
      sx = x;
      c[y][x] = '.';
    } else if (c[y][x] == 'g') {
      gy = y;
      gx = x;
    }
  }
  // prepare
  auto on_field = [&](int y, int x) {
    return 0 <= y and y < h and 0 <= x and x < w;
  };
  typedef queue<pair<int, int>> points_queue;
  auto bfs = [&](function<void(points_queue &)> init,
                 function<void(points_queue &, int, int, int, int)> update) {
    points_queue que;
    init(que);
    while (not que.empty()) {
      int y, x;
      tie(y, x) = que.front();
      que.pop();
      repeat(i, 4) {
        int ny = y + dy[i];
        int nx = x + dx[i];
        if (not on_field(ny, nx))
          continue;
        if (c[ny][nx] != '.')
          continue;
        update(que, y, x, ny, nx);
      }
    }
  };
  vector<vector<int>> goal(h, vector<int>(w, inf));
  bfs(
      [&](points_queue &que) {
        goal[gy][gx] = 0;
        que.push(make_pair(gy, gx));
      },
      [&](points_queue &que, int y, int x, int ny, int nx) {
        if (goal[ny][nx] == inf) {
          goal[ny][nx] = goal[y][x] + 1;
          que.push(make_pair(ny, nx));
        }
      });
  vector<vector<int>> jump(h, vector<int>(w, inf));
  bfs(
      [&](points_queue &que) {
        repeat(y, h) repeat(x, w) if (c[y][x] == '*') {
          jump[y][x] = 0;
          que.push(make_pair(y, x));
        }
      },
      [&](points_queue &que, int y, int x, int ny, int nx) {
        if (jump[ny][nx] == inf) {
          jump[ny][nx] = jump[y][x] + 1;
          que.push(make_pair(ny, nx));
        }
      });
  map<pair<int, int>, int> freq; // frequency
  int total = 0;
  int max_goal = 0;
  repeat(y, h) repeat(x, w) if (c[y][x] == '.') {
    freq[make_pair(goal[y][x], jump[y][x])] += 1;
    total += 1;
    if (goal[y][x] < inf)
      setmax(max_goal, goal[y][x]);
  }
  // calc
  long double e = INFINITY;
  repeat(estimate, max_goal + 1) {
    // E = f(E) = aE + b
    long double a = 0;
    long double b = 0;
    for (auto it : freq) {
      int g, j;
      tie(g, j) = it.first;
      int cnt = it.second;
      long double p = cnt / (long double)total;
      if (g == inf) {
        a += p;
        b += p * j;
      } else if (j == inf) {
        b += p * g;
      } else {
        if (g <= j + estimate) {
          b += p * g;
        } else {
          a += p;
          b += p * j;
        }
      }
    }
    setmin(e, b / (1 - a));
  }
  // output
  long double ans =
      goal[sy][sx] == inf ? jump[sy][sx] + e
      : jump[sy][sx] == inf
          ? goal[sy][sx]
          : min<long double>(goal[sy][sx],
                             jump[sy][sx] +
                                 e); // the answer can become grater than `int
                                     // inf`, so conditional op. is required.
  printf("%.12Lf\\n", ans);
  return 0;
}

Error: 0
0: 0.846154 1.38462 -> 9
1: 0.846154 1.38462 -> 9
2: 0.692308 1.69231 -> 5.5
3: 0.692308 1.69231 -> 5.5
4: 0.461538 2.61538 -> 4.85714
5: 0.384615 3 -> 4.875
6: 0.307692 3.46154 -> 5
7: 0.153846 4.53846 -> 5.36364
8: 0.153846 4.53846 -> 5.36364
e : 4.85714


Fixed submission:

#include <cmath>
#include <cstdio>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <tuple>
#include <vector>
#define repeat(i, n) for (int i = 0; (i) < (n); ++(i))
template <class T> bool setmax(T &l, T const &r) {
  if (not(l < r))
    return false;
  l = r;
  return true;
}
template <class T> bool setmin(T &l, T const &r) {
  if (not(r < l))
    return false;
  l = r;
  return true;
}
using namespace std;
const int inf = 1e9 + 7;
const int dy[] = {-1, 1, 0, 0};
const int dx[] = {0, 0, 1, -1};
int main() {
  // input
  int w, h;
  cin >> w >> h;
  vector<string> c(h);
  repeat(y, h) cin >> c[y];
  // modify input
  int sy, sx, gy, gx;
  repeat(y, h) repeat(x, w) {
    if (c[y][x] == 's') {
      sy = y;
      sx = x;
      c[y][x] = '.';
    } else if (c[y][x] == 'g') {
      gy = y;
      gx = x;
    }
  }
  // prepare
  auto on_field = [&](int y, int x) {
    return 0 <= y and y < h and 0 <= x and x < w;
  };
  typedef queue<pair<int, int>> points_queue;
  auto bfs = [&](function<void(points_queue &)> init,
                 function<void(points_queue &, int, int, int, int)> update) {
    points_queue que;
    init(que);
    while (not que.empty()) {
      int y, x;
      tie(y, x) = que.front();
      que.pop();
      repeat(i, 4) {
        int ny = y + dy[i];
        int nx = x + dx[i];
        if (not on_field(ny, nx))
          continue;
        if (c[ny][nx] != '.')
          continue;
        update(que, y, x, ny, nx);
      }
    }
  };
  vector<vector<int>> goal(h, vector<int>(w, inf));
  bfs(
      [&](points_queue &que) {
        goal[gy][gx] = 0;
        que.push(make_pair(gy, gx));
      },
      [&](points_queue &que, int y, int x, int ny, int nx) {
        if (goal[ny][nx] == inf) {
          goal[ny][nx] = goal[y][x] + 1;
          que.push(make_pair(ny, nx));
        }
      });
  vector<vector<int>> jump(h, vector<int>(w, inf));
  bfs(
      [&](points_queue &que) {
        repeat(y, h) repeat(x, w) if (c[y][x] == '*') {
          jump[y][x] = 0;
          que.push(make_pair(y, x));
        }
      },
      [&](points_queue &que, int y, int x, int ny, int nx) {
        if (jump[ny][nx] == inf) {
          jump[ny][nx] = jump[y][x] + 1;
          que.push(make_pair(ny, nx));
        }
      });
  map<pair<int, int>, int> freq; // frequency
  int total = 0;
  int max_goal = 0;
  repeat(y, h) repeat(x, w) if (c[y][x] == '.') {
    freq[make_pair(goal[y][x], jump[y][x])] += 1;
    total += 1;
    if (goal[y][x] < inf)
      setmax(max_goal, goal[y][x]);
  }
  // calc
  double e = INFINITY;
  repeat(estimate, max_goal + 1) {
    // E = f(E) = aE + b
    double a = 0;
    double b = 0;
    for (auto it : freq) {
      int g, j;
      tie(g, j) = it.first;
      int cnt = it.second;
      double p = cnt / (double)total;
      if (g == inf) {
        a += p;
        b += p * j;
      } else if (j == inf) {
        b += p * g;
      } else {
        if (g <= j + estimate) {
          b += p * g;
        } else {
          a += p;
          b += p * j;
        }
      }
    }
    cerr << estimate << ": " << a << " " << b << " -> " << b / (1 - a) << endl;
    setmin(e, b / (1 - a));
  }
  cerr << "e : " << e << endl;
  // output
  double ans =
      goal[sy][sx] == inf ? jump[sy][sx] + e
      : jump[sy][sx] == inf
          ? goal[sy][sx]
          : min<double>(goal[sy][sx],
                        jump[sy][sx] +
                            e); // the answer can become grater than `int inf`,
                                // so conditional op. is required.
  printf("%.12lf\\n", ans);
  return 0;
}