Problem p00888 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <bits/stdc++.h>

#define _overload(_1, _2, _3, name, ...) name
#define _rep(i, n) _range(i, 0, n)
#define _range(i, a, b) for (int i = int(a); i < int(b); ++i)
#define rep(...) _overload(__VA_ARGS__, _range, _rep, )(__VA_ARGS__)

#define _rrep(i, n) _rrange(i, n, 0)
#define _rrange(i, a, b) for (int i = int(a) - 1; i >= int(b); --i)
#define rrep(...) _overload(__VA_ARGS__, _rrange, _rrep, )(__VA_ARGS__)

#define _all(arg) begin(arg), end(arg)
#define uniq(arg) sort(_all(arg)), (arg).erase(unique(_all(arg)), end(arg))
#define getidx(ary, key) lower_bound(_all(ary), key) - begin(ary)
#define clr(a, b) memset((a), (b), sizeof(a))
#define bit(n) (1LL << (n))
#define popcount(n) (__builtin_popcountll(n))

template <class T> bool chmax(T &a, const T &b) {
  return (a < b) ? (a = b, 1) : 0;
}
template <class T> bool chmin(T &a, const T &b) {
  return (b < a) ? (a = b, 1) : 0;
}

using namespace std;

using R = double;
using edge = struct {
  int to;
};
using G = vector<vector<edge>>;
const R inf = 1e60;

using P = tuple<R, int>;
vector<P> points;
inline R distance(P a, P b) {
  R ax, bx;
  int ay, by;
  tie(ax, ay) = a, tie(bx, by) = b;
  return sqrt(max<R>(0.0, (bx - ax) * (bx - ax) + 1.0 * (by - ay) * (by - ay)));
}

int main(void) {
  int n;
  while (cin >> n, n) {
    set<int> altitude;
    int x[110], y[110];
    rep(i, n) cin >> x[i] >> y[i], altitude.insert(y[i]);

    points.clear();
    rep(i, n) points.push_back(P(x[i], y[i]));
    rep(i, n - 1) {
      int ly = y[i], hy = y[i + 1];
      if (ly > hy)
        swap(ly, hy);
      for (auto &ny : altitude) {
        if (ly < ny && ny < hy) {
          R nx = 1.0 * x[i] +
                 1.0 * (ny - y[i]) / (y[i + 1] - y[i]) * (x[i + 1] - x[i]);
          points.push_back(P(nx, ny));
        }
      }
    }

    uniq(points);

    const int m = points.size(), n = m * m, s = m - 1;
    map<int, R> dist;
    using state = tuple<R, int>;
    priority_queue<state, vector<state>, greater<state>> q;
    dist[s] = 0, q.push(state(0, s));

    while (!q.empty()) {
      R c;
      int v;
      tie(c, v) = q.top();
      q.pop();
      int i = v / m, j = v % m;
      rep(a, 3) rep(b, 3) {
        if (a == 1 && b == 1)
          continue;
        const int ni = i + (a - 1), nj = j + (b - 1);
        if (ni < 0 || m <= ni)
          continue;
        if (nj < 0 || m <= nj)
          continue;
        if (get<1>(points[ni]) != get<1>(points[nj]))
          continue;
        const int nv = m * ni + nj;
        R nc = c + distance(points[i], points[ni]) +
               distance(points[j], points[nj]);
        if (dist.find(nv) == end(dist))
          dist[nv] = inf;
        if (chmin(dist[nv], nc))
          q.push(state(nc, nv));
      }
    }

    R ans = inf;
    rep(i, m) if (dist.find(m * i + i) != end(dist))
        chmin(ans, dist[m * i + i]);
    cout.precision(20);
    cout << fixed << ans << endl;
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>

#define _overload(_1, _2, _3, name, ...) name
#define _rep(i, n) _range(i, 0, n)
#define _range(i, a, b) for (int i = int(a); i < int(b); ++i)
#define rep(...) _overload(__VA_ARGS__, _range, _rep, )(__VA_ARGS__)

#define _rrep(i, n) _rrange(i, n, 0)
#define _rrange(i, a, b) for (int i = int(a) - 1; i >= int(b); --i)
#define rrep(...) _overload(__VA_ARGS__, _rrange, _rrep, )(__VA_ARGS__)

#define _all(arg) begin(arg), end(arg)
#define uniq(arg) sort(_all(arg)), (arg).erase(unique(_all(arg)), end(arg))
#define getidx(ary, key) lower_bound(_all(ary), key) - begin(ary)
#define clr(a, b) memset((a), (b), sizeof(a))
#define bit(n) (1LL << (n))
#define popcount(n) (__builtin_popcountll(n))

template <class T> bool chmax(T &a, const T &b) {
  return (a < b) ? (a = b, 1) : 0;
}
template <class T> bool chmin(T &a, const T &b) {
  return (b < a) ? (a = b, 1) : 0;
}

using namespace std;

using R = double;
using edge = struct {
  int to;
};
using G = vector<vector<edge>>;
const R inf = 1e60;

using P = tuple<R, int>;
vector<P> points;
inline R distance(P a, P b) {
  R ax, bx;
  int ay, by;
  tie(ax, ay) = a, tie(bx, by) = b;
  return sqrt(max<R>(0.0, (bx - ax) * (bx - ax) + 1.0 * (by - ay) * (by - ay)));
}

vector<R> dijkstra(const G &graph, int s) {
  const int n = graph.size(), m = points.size();
  vector<R> dist(n, inf);
  using state = tuple<R, int>;
  priority_queue<state, vector<state>, greater<state>> q;
  dist[s] = 0, q.push(state(0, s));

  while (!q.empty()) {
    R c;
    int v;
    tie(c, v) = q.top();
    q.pop();
    for (auto &e : graph[v]) {
      int nv = e.to;
      R nc = c + distance(points[v / m], points[nv / m]) +
             distance(points[v % m], points[nv % m]);
      if (chmin(dist[nv], nc))
        q.push(state(nc, nv));
    }
  }

  return dist;
}

int main(void) {
  int n;
  while (cin >> n, n) {
    set<int> altitude;
    int x[110], y[110];
    rep(i, n) cin >> x[i] >> y[i], altitude.insert(y[i]);

    points.clear();
    rep(i, n) points.push_back(P(x[i], y[i]));
    rep(i, n - 1) {
      int ly = y[i], hy = y[i + 1];
      if (ly > hy)
        swap(ly, hy);
      for (auto &ny : altitude) {
        if (ly < ny && ny < hy) {
          R nx = 1.0 * x[i] +
                 1.0 * (ny - y[i]) / (y[i + 1] - y[i]) * (x[i + 1] - x[i]);
          points.push_back(P(nx, ny));
        }
      }
    }
    uniq(points);
    int m = points.size();

    G graph(m * m);
    rep(i, m) rep(j, m) {
      if (get<1>(points[i]) != get<1>(points[j]))
        continue;
      int v = m * i + j;
      rep(a, 3) rep(b, 3) {
        if (a == 1 && b == 1)
          continue;
        const int ni = i + (a - 1), nj = j + (b - 1);
        if (ni < 0 || m <= ni)
          continue;
        if (nj < 0 || m <= nj)
          continue;
        if (get<1>(points[ni]) != get<1>(points[nj]))
          continue;
        const int nv = m * ni + nj;
        graph[v].push_back({nv});
      }
    }

    const int s = m - 1;
    vector<R> dist = dijkstra(graph, s);
    R ans = inf;
    rep(i, m) chmin(ans, dist[m * i + i]);
    cout.precision(20);
    cout << fixed << ans << endl;
  }
  return 0;
}