C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
using Real = double;
using Point = complex<Real>;
#define x real
#define y imag
constexpr Real eps = 1E-9;
int sign(const Real &x) {
return x < -eps ? -1 : x > eps ? 1 : 0;
}
struct Line {
Point a, b;
Line() {}
Line(const Point &a, const Point &b) : a(a), b(b) {}
};
struct Segment : Line {
Segment() = default;
using Line::Line;
Real len() const {
return abs(a - b);
}
};
Real cross(const Point &a, const Point &b) {
return (conj(a) * b).y();
}
Real dot(const Point &a, const Point &b) {
return (conj(a) * b).x();
}
int onLeft(const Point &p, const Line &l) {
return sign(cross(l.b - l.a, p - l.a));
}
bool collinear(const Line &l1, const Line &l2) {
return sign(cross(l1.b - l1.a, l2.b - l2.a)) == 0 && sign(cross(l1.b - l1.a, l1.b - l2.a)) == 0;
}
bool intersect(const Segment &s1, const Segment &s2) {
return onLeft(s2.a, s1) * onLeft(s2.b, s1) <= 0 && onLeft(s1.a, s2) * onLeft(s1.b, s2) <= 0;
}
bool onSegment(const Point &p, const Segment &s) {
return sign(cross(p - s.a, s.b - s.a)) == 0 && sign(dot(p - s.a, p - s.b)) <= 0;
}
// -1 : on, 0 : out, 1 : in
int contains(const Point &p, const vector<Point> &g) {
int gsz = g.size();
bool in = false;
for(int i = 0; i < gsz; i++) {
Point a = g[i] - p, b = g[(i + 1) % gsz] - p;
if (a.y() > b.y()) swap(a, b);
if (a.y() <= 0 && 0 < b.y() && cross(a, b) < 0) in = !in;
if (cross(a, b) == 0 && dot(a, b) <= 0) return -1;
}
return in ? 1 : 0;
}
void solve(int n) {
vector<Point> a(n);
for (int i = 0; i < n; i++) {
int x, y;
cin >> x >> y;
a[i] = Point(x, y);
}
int x, y;
cin >> x >> y;
Point s = Point(x, y);
cin >> x >> y;
Point t = Point(x, y);
auto check = [&](const Segment &S) {
for (int i = 0; i < n; i++) {
Segment T(a[i], a[(i + 1) % n]);
if (collinear(S, T)) {
continue;
}
if (intersect(S, T) && !onSegment(S.a, T) && !onSegment(S.b, T)) {
return false;
}
}
Point mid = (S.a + S.b) / 2.0;
if (contains(mid, a) == 1){
return false;
}
return true;
};
vector<Point> P;
P.push_back(s);
P.push_back(t);
for (int i = 0; i < n; i++) {
P.push_back(a[i]);
}
int m = P.size();
vector<vector<pair<int, double>>> g(m);
for (int i = 0; i < m; i++) {
for (int j = i + 1; j < m; j++) {
Segment S(P[i], P[j]);
if (check(S)) {
g[i].push_back({j, S.len()});
g[j].push_back({i, S.len()});
}
}
}
priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> q;
vector<int> vis(m);
vector<double> dis(m, 1E9);
dis[0] = 0;
q.push({dis[0], 0});
while (!q.empty()) {
double u = q.top().first;
int v = q.top().second;
q.pop();
if (v == 1) {
cout << dis[1] << '\n';
return;
}
if (!vis[v]) {
vis[v] = 1;
for (auto d : g[v]) {
int x = d.first;
double w = d.second;
if (dis[x] > dis[v] + w) {
dis[x] = dis[v] + w;
q.push({dis[x], x});
}
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout << fixed << setprecision(15);
int n;
while (cin >> n) {
solve(n);
}
return 0;
}