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

#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <time.h>
#include <utility>
#include <vector>
using namespace std;
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T> inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EXIST(s, e) ((s).find(e) != (s).end())
#define EXIST2(s, e) (find(ALL(s), (e)) != (s).end())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
const double EPS = 1e-9;
const double PI = acos(-1.0);

typedef vector<double> vd;
typedef vector<vd> vvd;
typedef pair<double, double> pdd;

#define EQ(a, b) (abs((a) - (b)) < EPS)

struct node {
  int left, right;
  double cost;
  node(int left, int right, double cost)
      : left(left), right(right), cost(cost) {}
  bool operator<(const node &other) const { return cost > other.cost; }
};
const int MAX = INT_MAX / 10;

double dist(pdd &a, pdd &b) {
  double dx = a.first - b.first;
  double dy = a.second - b.second;
  return sqrt(dx * dx + dy * dy);
}

int main() {
  cout.precision(20);
  int n;
  while (cin >> n, n) {
    vector<pdd> pp(n);
    REP(i, n) { cin >> pp[i].first >> pp[i].second; }
    vector<pdd> p(pp);
    REP(i, n) {
      REP(j, n - 1) {
        if ((pp[j].second < pp[i].second && pp[i].second < pp[j + 1].second) ||
            (pp[j].second > pp[i].second && pp[i].second > pp[j + 1].second)) {
          double ratio = abs(pp[j].second - pp[i].second) /
                         abs(pp[j].second - pp[j + 1].second);
          double x = pp[j].first + (pp[j + 1].first - pp[j].first) * ratio;
          p.push_back(make_pair(x, pp[i].second));
        }
      }
    }
    sort(ALL(p));
    p.erase(unique(ALL(p)), p.end());

    int sz = p.size();
    priority_queue<node> q;
    q.push(node(0, sz - 1, 0));
    map<pii, double> cost;
    cost[make_pair(0, sz - 1)] = 0;
    while (!q.empty()) {
      node cnode = q.top();
      q.pop();
      if (cost[make_pair(cnode.left, cnode.right)] < cnode.cost) {
        continue;
      }
      for (int i = -1; i <= 1; i++) {
        for (int j = -1; j <= 1; j++) {
          int nleft = cnode.left + i;
          int nright = cnode.right + j;
          if (nleft >= 0 && nright < sz && nleft <= nright &&
              EQ(p[nleft].second, p[nright].second)) {
            double d1 = dist(p[nleft], p[cnode.left]);
            double d2 = dist(p[nright], p[cnode.right]);
            double newcost = cnode.cost + d1 + d2;
            pii p = make_pair(nleft, nright);
            if (!EXIST(cost, p)) {
              cost[p] = INT_MAX;
            }
            if (cost[p] > newcost) {
              cost[p] = newcost;
              q.push(node(nleft, nright, newcost));
            }
          }
        }
      }
    }
    double ans = INT_MAX;
    REP(i, sz) { ans = min(ans, cost[make_pair(i, i)]); }
    cout << ans << endl;
  }
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <time.h>
#include <utility>
#include <vector>
using namespace std;
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T> inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EXIST(s, e) ((s).find(e) != (s).end())
#define EXIST2(s, e) (find(ALL(s), (e)) != (s).end())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
const double EPS = 1e-9;
const double PI = acos(-1.0);

typedef vector<double> vd;
typedef vector<vd> vvd;
typedef pair<double, double> pdd;

#define EQ(a, b) (abs((a) - (b)) < EPS)

struct node {
  int left, right;
  double cost;
  node(int left, int right, double cost)
      : left(left), right(right), cost(cost) {}
  bool operator<(const node &other) const { return cost > other.cost; }
};
const int MAX = INT_MAX / 10;

double dist(pdd &a, pdd &b) {
  double dx = a.first - b.first;
  double dy = a.second - b.second;
  return sqrt(dx * dx + dy * dy);
}

int main() {
  cout.precision(20);
  int n;
  while (cin >> n, n) {
    vector<pdd> pp(n);
    REP(i, n) { cin >> pp[i].first >> pp[i].second; }
    vector<pdd> p(pp);
    REP(i, n) {
      REP(j, n - 1) {
        if ((pp[j].second < pp[i].second && pp[i].second < pp[j + 1].second) ||
            (pp[j].second > pp[i].second && pp[i].second > pp[j + 1].second)) {
          double ratio = abs(pp[j].second - pp[i].second) /
                         abs(pp[j].second - pp[j + 1].second);
          double x = pp[j].first + (pp[j + 1].first - pp[j].first) * ratio;
          p.push_back(make_pair(x, pp[i].second));
        }
      }
    }
    sort(ALL(p));
    p.erase(unique(ALL(p)), p.end());

    int sz = p.size();
    priority_queue<node> q;
    q.push(node(0, sz - 1, 0));
    vvd cost(sz, vd(sz, MAX));
    cost[0][sz - 1] = 0;
    while (!q.empty()) {
      node cnode = q.top();
      q.pop();
      if (cost[cnode.left][cnode.right] < cnode.cost) {
        continue;
      }
      for (int i = -1; i <= 1; i++) {
        for (int j = -1; j <= 1; j++) {
          int nleft = cnode.left + i;
          int nright = cnode.right + j;
          if (nleft >= 0 && nright < sz && nleft <= nright &&
              EQ(p[nleft].second, p[nright].second)) {
            double d1 = dist(p[nleft], p[cnode.left]);
            double d2 = dist(p[nright], p[cnode.right]);
            double newcost = cnode.cost + d1 + d2;
            if (cost[nleft][nright] > newcost) {
              cost[nleft][nright] = newcost;
              q.push(node(nleft, nright, newcost));
            }
          }
        }
      }
    }
    double ans = INT_MAX;
    REP(i, sz) { ans = min(ans, cost[i][i]); }
    cout << ans << endl;
  }
}