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

#include <algorithm>
#include <cmath>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

inline long double add(long double a, long double b) {
  return abs(a + b) < (1e-11) * (abs(a) + abs(b)) ? 0.0 : a + b;
}

struct vec {
  long double x, y;
  vec operator-(vec b) { return (vec){add(x, -b.x), add(y, -b.y)}; }
  vec operator+(vec b) { return (vec){add(x, b.x), add(y, b.y)}; }
  vec operator*(long double d) { return (vec){x * d, y * d}; }
  bool operator==(vec b) { return x == b.x && y == b.y; }
  bool operator!=(vec b) { return x != b.x || y != b.y; }
  long double dot(vec v) { return add(x * v.x, y * v.y); }
  long double cross(vec v) { return add(x * v.y, -y * v.x); }
  long double norm() { return sqrt(x * x + y * y); }
};

int ccw(vec &a, vec &b, vec &c) {
  vec ab = b - a, ac = c - a;
  long double o = ab.cross(ac);
  if (o > 0)
    return 1; // CCW
  if (o < 0)
    return -1; // CW
  if (ab.dot(ac) < 0) {
    return 2; // C-A-B
  } else {
    if (ab.dot(ab) < ac.dot(ac)) {
      return -2; // A-B-C
    } else {
      return 0; // A-C-B
    }
  }
}

void print_path(vector<pair<int, vec>> &P);
long double t_sum(vector<pair<int, vec>> &P, long double tg, long double tw);

vec ternarysearch(vec &p0, vec &p1, vec &p2, long double tg, long double tw) {
  //???p0??????p2??????????????????p2p3?????????????????£?????????????????§????????????????????????????????????
  long double left = 1.0 / 3.0, right = 2.0 / 3.0;
  long double t, t1, t2;
  vec P1, P2;
  while (true) {
    P1 = p1 * (1 - left) + p2 * left;
    P2 = p1 * (1 - right) + p2 * right;
    t1 = (p0 - P1).norm() * tw + (p2 - P1).norm() * tg;
    t2 = (p0 - P2).norm() * tw + (p2 - P2).norm() * tg;
    if (abs(t1 - t2) < 1e-11) {
      t = (left + right) / 2;
      if (1.0 - t < 1e-8) {
        return p2;
      } else if (t < 1e-8) {
        return p1;
      } else {
        return P1;
      }
    }
    if (t1 < t2) {
      right = (2 * left + right) / 3;
      left = 2 * left - right;
    } else {
      left = (2 * right + left) / 3;
      right = 2 * right - left;
    }
  }
}

struct Segment {
  int begin, end;
  vector<int> P;
  Segment(int a, int b) {
    begin = a, end = b;
    P.push_back(a);
    P.push_back(b);
  }
};

struct Edge {
  int to;
  long double t;
  Edge(int a, long double b) { to = a, t = b; }
};

struct Point {
  vec v;
  vector<Edge> E;
  Point(vec v) { this->v = v; }
};

long double solve(vector<vec> &v, vec &S, vec &T, long double tg,
                  long double tw) {
  int n = v.size();
  vector<Point> V;
  for (int i = 0; i < n; i++) {
    if ((v[i] - S).norm() < 1e-8) { // S?????????????????????
      V.push_back(Point(S));
      for (int j = i + 1; j != i; j = (j + 1) % n) {
        V.push_back(Point(v[j]));
      }
      break;
    } else if (!ccw(v[i], v[(i + 1) % n], S)) { // S??????????????????
      V.push_back(Point(S));
      i = (i + 1) % n;
      for (int j = 0; j < n; j++) {
        V.push_back(Point(v[(i + j) % n]));
      }
      break;
    }
  }
  n = V.size();
  vector<Segment> L;
  for (int i = 0; i < V.size(); i++) {
    L.push_back(Segment(i, (i + 1) % n));
  }
  V.push_back(T);
  n = V.size();
  int iT = V.size() - 1;
  for (int i = 0; i < n; i++) {
    for (auto &s : L) {
      if (s.begin == i || s.end == i)
        continue;
      vec M;
      M = ternarysearch(V[i].v, V[s.begin].v, V[s.end].v, tg, tw);
      if (M != V[s.begin].v && M != V[s.end].v) {
        V.push_back(M);
        V.back().E.push_back(Edge(i, (V[i].v - M).norm() * tw));
        V[i].E.push_back(Edge(V.size() - 1, (V[i].v - M).norm() * tw));
        s.P.push_back(V.size() - 1);
      }
      M = ternarysearch(V[i].v, V[s.end].v, V[s.begin].v, tg, tw);
      if (M != V[s.begin].v && M != V[s.end].v) {
        V.push_back(M);
        V.back().E.push_back(Edge(i, (V[i].v - M).norm() * tw));
        V[i].E.push_back(Edge(V.size() - 1, (V[i].v - M).norm() * tw));
        s.P.push_back(V.size() - 1);
      }
    }
  }
  //????§???¢?????????+S+T????£?????????¶
  for (int i = 0; i <= iT; i++) {
    for (int j = i + 2; j <= iT; j++) {
      V[i].E.push_back(Edge(j, (V[i].v - V[j].v).norm() * tw));
      V[j].E.push_back(Edge(i, (V[i].v - V[j].v).norm() * tw));
    }
  }

  //????§???¢????????????????????????????????¶???
  for (auto &s : L) {
    for (auto &p1 : s.P) {
      for (auto &p2 : s.P) {
        if (p1 != p2) {
          V[p1].E.push_back(Edge(p2, (V[p1].v - V[p2].v).norm() * tg));
          V[p2].E.push_back(Edge(p1, (V[p1].v - V[p2].v).norm() * tg));
        }
      }
    }
  }
  //?§???????0????????????iT?????????????????????
  typedef pair<long double, int> Q;
  priority_queue<Q, vector<Q>, greater<Q>> que;
  long double minimum_time[V.size()];
  fill(minimum_time, minimum_time + V.size(), 1e10);
  int s = 0;
  minimum_time[s] = 0;
  que.push(Q(0, s));
  while (!que.empty()) {
    Q q = que.top();
    que.pop();
    int i = q.second;
    if (i == iT)
      return minimum_time[i];
    if (minimum_time[i] < q.first)
      continue;
    for (auto &e : V[i].E) {
      if (minimum_time[e.to] > minimum_time[i] + e.t) {
        minimum_time[e.to] = minimum_time[i] + e.t;
        que.push(Q(minimum_time[e.to], e.to));
      }
    }
  }
  return 0;
}

int main() {
  int n;
  long double tg, tw;
  vec S, T;
  vector<vec> V;

  while (cin >> n, n != 0) {
    V.clear();
    for (int i = 0; i < n; i++) {
      long double x, y;
      cin >> x >> y;
      V.push_back((vec){.x = x, .y = y});
    }
    cin >> tg >> tw;
    cin >> S.x >> S.y;
    cin >> T.x >> T.y;

    cout.precision(8);
    cout << fixed;
    cout << solve(V, S, T, tg, tw) << endl;
  }
  return 0;
}

Error: WA

Fixed submission:

#include <algorithm>
#include <cmath>
#include <iostream>
#include <vector>

using namespace std;

inline double add(double a, double b) {
  return abs(a + b) < (1e-10) * (abs(a) + abs(b)) ? 0.0 : a + b;
}

struct vec {
  double x, y;
  vec operator-(vec b) { return (vec){add(x, -b.x), add(y, -b.y)}; }
  vec operator+(vec b) { return (vec){add(x, b.x), add(y, b.y)}; }
  vec operator*(double d) { return (vec){x * d, y * d}; }
  bool operator==(vec b) { return x == b.x && y == b.y; }
  double dot(vec v) { return add(x * v.x, y * v.y); }
  double cross(vec v) { return add(x * v.y, -y * v.x); }
  double norm() { return sqrt(x * x + y * y); }
};

int ccw(vec &a, vec &b, vec &c) {
  vec ab = b - a, ac = c - a;
  double o = ab.cross(ac);
  if (o > 0)
    return 1; // CCW
  if (o < 0)
    return -1; // CW
  if (ab.dot(ac) < 0) {
    return 2; // C-A-B
  } else {
    if (ab.dot(ab) < ac.dot(ac)) {
      return -2; // A-B-C
    } else {
      return 0; // A-C-B
    }
  }
}

void print_path(vector<pair<int, vec>> &P);
double t_sum(vector<pair<int, vec>> &P, double tg, double tw);

pair<int, vec> bisectionWW(vector<pair<int, vec>> &P, int i, double tg,
                           double tw) {
  return P[i];
}

pair<int, vec> bisectionGW(vector<pair<int, vec>> &P, int i, double tg,
                           double tw) {
  double delta = 0.25, t = 0.5;
  double t0, t1, t2;
  vec P1, P2, &p1 = P[i].second, &p2 = P[i + 1].second, &p3 = P[i + 2].second;

  t0 = (p1 - p2).norm() * 0.5 * tg + (p3 - (p1 + p2) * 0.5).norm() * tw;
  while (true) {
    P1 = p1 * (1 - (t + delta)) + p2 * (t + delta);
    P2 = p1 * (1 - (t - delta)) + p2 * (t - delta);
    t1 = (p1 - P1).norm() * tg + (p3 - P1).norm() * tw;
    t2 = (p1 - P2).norm() * tg + (p3 - P2).norm() * tw;
    if (abs(t0 - t1) < 1e-10) {
      if (1.0 - t < 1e-8) {
        return pair<int, vec>(1, p2);
      } else if (t < 1e-8) {
        // P.erase(P.begin()+i+1);
        // P[i].first=1;
        return pair<int, vec>(1, p1);
      } else {
        // P[i+1].first=1;
        // P[i+1].second=P1;
        return pair<int, vec>(1, P1);
      }
    }
    if (t0 < t1 && t0 < t2) {
      delta /= 2;
      continue;
    }
    if (t1 < t0) {
      t += delta;
      delta /= 2;
      t0 = t1;
      continue;
    }
    if (t2 < t0) {
      t -= delta;
      delta /= 2;
      t0 = t2;
      continue;
    }
  }
}

pair<int, vec> bisectionWG(vector<pair<int, vec>> &P, int i, double tg,
                           double tw) {
  double delta = 0.25, t = 0.5;
  double t0, t1, t2;
  vec P1, P2, &p1 = P[i].second, &p2 = P[i + 1].second, &p3 = P[i + 2].second;

  t0 = ((p3 + p2) * 0.5 - p1).norm() * tw + (p3 - p2).norm() * 0.5 * tg;
  while (true) {
    P1 = p2 * (1 - (t + delta)) + p3 * (t + delta);
    P2 = p2 * (1 - (t - delta)) + p3 * (t - delta);
    t1 = (p1 - P1).norm() * tw + (p3 - P1).norm() * tg;
    t2 = (p1 - P2).norm() * tw + (p3 - P2).norm() * tg;
    if (abs(t0 - t1) < 1e-10) {
      if (1.0 - t < 1e-8) {
        // P.erase(P.begin()+i+1);
        // P[i].first=1;
        return pair<int, vec>(0, p3);
      } else if (t < 1e-8) {
        return pair<int, vec>(0, p2);
      } else {
        // P[i].first=1;
        // P[i+1].first=1;
        // P[i+1].second=P1;
        return pair<int, vec>(0, P1);
      }
    }
    if (t0 < t1 && t0 < t2) {
      delta /= 2;
      continue;
    }
    if (t1 < t0) {
      t += delta;
      delta /= 2;
      t0 = t1;
      continue;
    }
    if (t2 < t0) {
      t -= delta;
      delta /= 2;
      t0 = t2;
      continue;
    }
  }
}

pair<int, vec> bisectionGG(vector<pair<int, vec>> &P, int i, double tg,
                           double tw) {
  pair<int, vec> M1, M2;
  double t1, t2;
  M1 = bisectionGW(P, i, tg, tw);
  t1 = (P[i].second - M1.second).norm() * tg +
       (P[i + 2].second - M1.second).norm() * tw;
  M2 = bisectionWG(P, i, tg, tw);
  t2 = (P[i].second - M2.second).norm() * tw +
       (P[i + 2].second - M2.second).norm() * tg;
  if (t1 < t2) {
    return M1;
  } else {
    P[i].first = 1;
    return M2;
  }
}

bool bisection(vector<pair<int, vec>> &P, int i, double tg,
               double tw) { // P[i],P[i+1],P[i+2]?????????
  // cout << i << " " << i+1 << " " << i+2 << endl;
  double delta = 0.25, t = 0.5;
  double t0, t1, t2;
  pair<int, vec> p;
  vec P1, P2, &p1 = P[i].second, &p2 = P[i + 1].second, &p3 = P[i + 2].second;
  if (P[i].first == 1 && P[i + 1].first == 1) {
    p = bisectionWW(P, i, tg, tw);
  }
  if (P[i].first == 0 && P[i + 1].first == 1) {
    p = bisectionGW(P, i, tg, tw);
  }
  if (P[i].first == 1 && P[i + 1].first == 0) {
    p = bisectionWG(P, i, tg, tw);
  }
  if (P[i].first == 0 && P[i + 1].first == 0) {
    p = bisectionGG(P, i, tg, tw);
  }
  if (P[i].second == p.second || p.second == P[i + 2].second) {
    P.erase(P.begin() + i + 1);
    P[i].first = 1;
    return true; //????´???°????????£???
  } else {
    if (p.second == P[i + 1].second) {
      return false;
    } else {
      P[i + 1] = p;
      return false;
    }
  }
}

double t_sum(vector<pair<int, vec>> &P, double tg, double tw) {
  int n = P.size() - 1;
  double t = 0;
  for (int i = 0; i < n; i++) {
    if (P[i].first == 1) {
      t += (P[i + 1].second - P[i].second).norm() * tw;
    } else {
      t += (P[i + 1].second - P[i].second).norm() * tg;
    }
  }
  return t;
}

void print_path(vector<pair<int, vec>> &P) {
  for (auto &i : P) {
    switch (i.first) {
    case 0:
      cout << 'G';
      break;
    case 1:
      cout << 'W';
      break;
    case -1:
      cout << "END";
      break;
    }
    cout << "( " << i.second.x << ", " << i.second.y << " )" << endl;
  }
}

double optimize(vector<pair<int, vec>> &P, double tg, double tw) {
  double t0, t1;
  t0 = t_sum(P, tg, tw);
  int c = 0;
  // cout << "RUN" << c++ << " " << t_sum(P,tg,tw) << endl;
  // print_path(P);
  while (true) {
    for (int i = P.size() - 3; i >= 0; i += 0) {
      if (bisection(P, i, tg, tw)) {
        i = min((int)P.size() - 3, i);
      } else {
        i--;
      }
    }
    // cout << "RUN" << c++ << " " << t_sum(P,tg,tw) << endl;
    // print_path(P);
    t1 = t_sum(P, tg, tw);
    if (abs(t0 - t1) < 1e-9) {
      return min(t0, t1);
    } else {
      t0 = t1;
    }
  }
}

double solve(vector<vec> &V, vec &S, vec &T, double tg, double tw) {
  int n = V.size();
  vector<pair<int, vec>> P1, P2; // 0:g 1:w
  double d = 1e10;
  vec C;
  for (int i = 0; i < n; i++) {
    double k = (V[(i + 1) % n] - V[i]).dot(T - V[i]) /
               (V[(i + 1) % n] - V[i]).dot(V[(i + 1) % n] - V[i]);
    if (0 <= k && k <= 1) {
      if ((T - (V[i + 1] * k + V[i] * (1 - k))).norm() < d) {
        d = (T - (V[i + 1] * k + V[i] * (1 - k))).norm();
        C = V[i + 1] * k + V[i] * (1 - k);
      }
    }
  }
  for (int i = 0; i < n; i++) {
    if ((V[i] - C).norm() < 1e-10) { // C?????????????????????
      break;
    } else if (!ccw(V[i], V[(i + 1) % n], C)) { // C??????????????????
      V.insert(V.begin() + (i + 1) % n, C);
      n++;
      break;
    }
  }
  for (int i = 0; i < n; i++) {
    if ((V[i] - S).norm() < 1e-10) { // S?????????????????????
      break;
    } else if (!ccw(V[i], V[(i + 1) % n], S)) { // S??????????????????
      V.insert(V.begin() + (i + 1) % n, S);
      n++;
      break;
    }
  }

  for (int i = 0; i < n; i++) { // Path????????????
    if ((V[i] - S).x == 0 && (V[i] - S).y == 0) {
      P1.push_back(pair<int, vec>(0, V[i]));
      P2.push_back(pair<int, vec>(0, V[i]));
      int j = (i + 1) % n;
      while (true) {
        if ((V[j] - C).x == 0 && (V[j] - C).y == 0) {
          P1.push_back(pair<int, vec>(1, V[j]));
          P1.push_back(pair<int, vec>(-1, T));
          break;
        } else {
          P1.push_back(pair<int, vec>(0, V[j]));
          j = (j + 1) % n;
        }
      }
      j = (i + n - 1) % n;
      while (true) {
        if ((V[j] - C).x == 0 && (V[j] - C).y == 0) {
          P2.push_back(pair<int, vec>(1, V[j]));
          P2.push_back(pair<int, vec>(-1, T));
          break;
        } else {
          P2.push_back(pair<int, vec>(0, V[j]));
          j = (j + n - 1) % n;
        }
      }
      break;
    }
  }
  // cout << "P1\\n";
  double path1 = optimize(P1, tg, tw);
  // cout << "\\n\\nP2\\n";
  double path2 = optimize(P2, tg, tw);
  return min(path1, path2);
}

int main() {
  int n;
  double tg, tw;
  vec S, T;
  vector<vec> V;

  while (cin >> n, n != 0) {
    V.clear();
    for (int i = 0; i < n; i++) {
      double x, y;
      cin >> x >> y;
      V.push_back((vec){.x = x, .y = y});
    }
    cin >> tg >> tw;
    cin >> S.x >> S.y;
    cin >> T.x >> T.y;

    cout.precision(8);
    cout << fixed;
    cout << solve(V, S, T, tg, tw) << endl;
  }
  return 0;
}