Problem:
Problem D
動く点 P と愉快な仲間たち Q, R
二次元平面上に凸
N
角形がある．各頂点には反時計回りに
1
から
N
までの番号がつけられている．
この多角形の周上に，三点
P
,
Q
,
R
がある．はじめ，
P
,
Q
,
R
はそれぞれ，多角形の頂点
k
P
,
k
Q
,
k
R
と同じ座標にある．その後，
P
,
Q
,
R
は同じ速さで，多角形の周上を反時計回りに一周する．
時々刻々と変化する三角形
PQR
の形状．あなたには，この三角形の面積の最小値を求めてほしい．なお，
P
,
Q
,
R
が同一直線上に存在する場合，三角形
PQR
の面積は
0
であるものとみなす．
Input
入力は
50
個以下のデータセットからなる．各データセットは次の形式で表される．
N
K
P
K
Q
K
R
x
1
y
1
...
x
N
y
N
N
は凸多角形の頂点数であり，
3 ≤ N ≤ 1,000
を満たす．
K
P
,
K
Q
,
K
R
はそれぞれ，点
P
,
Q
,
R
がはじめに存在する頂点の番号であり，
1 ≤ K
P
< K
Q
< K
R
≤ N
を満たす．
各
(x
i
, y
i
)
は凸多角形の
i
番目の頂点の座標であり，
-10,000 ≤ x
i
,y
i
≤ 10,000
を満たす．凸多角形の座標は反時計回りで与えられることが保証される．
入力される数値はいずれも整数である．
入力の終わりは 4 つのゼロからなる行で表される．
Output
各データセットに対し，三角形
PQR
の面積の最小値を，一行に出力せよ．出力は
10
-4
を超える誤差を含んではならない．
Sample Input
4 1 2 3
10 10
-10 10
-10 -10
10 -10
3 1 2 3
-10 -10
10 -10
0 10
0 0 0 0
Output for the Sample Input
100.000000000000000
49.442719099991588

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

const double EPS = 1e-11;
const double INF = 1e18;

struct Point {
    double x, y;
    Point operator-(const Point& p) const { return {x - p.x, y - p.y}; }
};

double cross(Point a, Point b) {
    return a.x * b.y - a.y * b.x;
}

double triangle_area(Point a, Point b, Point c) {
    return abs(cross(b - a, c - a)) / 2.0;
}

double edge_length(Point a, Point b) {
    return hypot(b.x - a.x, b.y - a.y);
}

Point get_point(double d, const vector<Point>& vertices, const vector<double>& prefix_sum, double perimeter) {
    d = fmod(d, perimeter);
    if (d < 0) d += perimeter;
    int idx = lower_bound(prefix_sum.begin(), prefix_sum.end(), d) - prefix_sum.begin() - 1;
    double rem = d - prefix_sum[idx];
    int u = idx;
    int v = (u + 1) % (int)vertices.size();
    double ratio = (prefix_sum[idx+1] - prefix_sum[idx]) ? rem / (prefix_sum[idx+1] - prefix_sum[idx]) : 0;
    return {vertices[u].x + ratio * (vertices[v].x - vertices[u].x), vertices[u].y + ratio * (vertices[v].y - vertices[u].y)};
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    while (true) {
        int N;
        cin >> N;
        if (N == 0) break;
        int P0, Q0, R0;
        cin >> P0 >> Q0 >> R0;
        P0--; Q0--; R0--;
        vector<Point> V(N);
        for (int i = 0; i < N; ++i) cin >> V[i].x >> V[i].y;
        vector<double> prefix_sum(N + 1);
        for (int i = 0; i < N; ++i) prefix_sum[i+1] = prefix_sum[i] + edge_length(V[i], V[(i+1)%N]);
        double perimeter = prefix_sum[N];
        auto get_dist = [&](int a, int b) {
            if (a == b) return 0.0;
            double sum = 0;
            int cur = a;
            while (cur != b) {
                sum += edge_length(V[cur], V[(cur+1)%N]);
                cur = (cur + 1) % N;
            }
            return sum;
        };
        double D_Q = get_dist(P0, Q0);
        double D_R = get_dist(P0, R0);
        vector<double> crit;
        for (int i = 0; i <= N; ++i) crit.push_back(prefix_sum[i]);
        for (int i = 0; i < N; ++i) {
            double pos = get_dist(P0, i) - D_Q;
            if (pos < 0) pos += perimeter;
            crit.push_back(fmod(pos, perimeter));
        }
        for (int i = 0; i < N; ++i) {
            double pos = get_dist(P0, i) - D_R;
            if (pos < 0) pos += perimeter;
            crit.push_back(fmod(pos, perimeter));
        }
        sort(crit.begin(), crit.end());
        crit.erase(unique(crit.begin(), crit.end(), [](double a, double b){ return abs(a - b) < EPS; }), crit.end());
        double min_area = INF;
        for (double d : crit) {
            Point p = get_point(d, V, prefix_sum, perimeter);
            Point q = get_point(fmod(d + D_Q, perimeter), V, prefix_sum, perimeter);
            Point r = get_point(fmod(d + D_R, perimeter), V, prefix_sum, perimeter);
            double area = triangle_area(p, q, r);
            min_area = min(min_area, area);
        }
        for (size_t i = 0; i + 1 < crit.size(); ++i) {
            double l = crit[i], r = crit[i+1];
            if (r - l < EPS) continue;
            for (int it = 0; it < 150; ++it) {
                double m1 = l + (r - l)/3;
                double m2 = r - (r - l)/3;
                Point p1 = get_point(m1, V, prefix_sum, perimeter);
                Point q1 = get_point(fmod(m1 + D_Q, perimeter), V, prefix_sum, perimeter);
                Point r1 = get_point(fmod(m1 + D_R, perimeter), V, prefix_sum, perimeter);
                Point p2 = get_point(m2, V, prefix_sum, perimeter);
                Point q2 = get_point(fmod(m2 + D_Q, perimeter), V, prefix_sum, perimeter);
                Point r2 = get_point(fmod(m2 + D_R, perimeter), V, prefix_sum, perimeter);
                double f1 = triangle_area(p1, q1, r1);
                double f2 = triangle_area(p2, q2, r2);
                if (f1 < f2) r = m2;
                else l = m1;
            }
            Point p_l = get_point(l, V, prefix_sum, perimeter);
            Point q_l = get_point(fmod(l + D_Q, perimeter), V, prefix_sum, perimeter);
            Point r_l = get_point(fmod(l + D_R, perimeter), V, prefix_sum, perimeter);
            Point p_r = get_point(r, V, prefix_sum, perimeter);
            Point q_r = get_point(fmod(r + D_Q, perimeter), V, prefix_sum, perimeter);
            Point r_r = get_point(fmod(r + D_R, perimeter), V, prefix_sum, perimeter);
            min_area = min(min_area, triangle_area(p_l, q_l, r_l));
            min_area = min(min_area, triangle_area(p_r, q_r, r_r));
        }
        cout.precision(12);
        cout << fixed << min_area << "\n";
    }
    return 0;
}
accuracy: 1
time_ms: 420
memory_kb: 3744
final_rank: 11

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

// #ifndef ONLINE_JUDGE
// #define _GLIBCXX_DEBUG // 配列外参照のエラー
// #endif

// スタンダードライブラリ
#include <bits/stdc++.h>
using namespace std;

// 型関連
using ll = long long;
using lint = long long;
using pll = pair<ll, ll>;
using plll = tuple<ll, ll, ll>;
using pii = pair<int, int>;
using piii = tuple<ll, ll, ll>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vvvvi = vector<vector<vector<vector<int>>>>;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
using vvvl = vector<vector<vector<ll>>>;
using vvvvl = vector<vector<vector<vector<ll>>>>;

template <class T> using prique = priority_queue<T>;
template <class T> void chmin(T &a, T b) {
    if (a > b)
        a = b;
}
template <class T> void chmax(T &a, T b) {
    if (a < b)
        a = b;
}

#define all(v) v.begin(), v.end()

// 型定数
constexpr ll mod = 998244353;
constexpr ll MOD = 1000000007;
int INF32 = 2e9;
ll INF64 = 9e18;
#define endl '\n';

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

/////////////////////////// print関連
template <typename T> void print(vector<T> A);
void print();
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail);
void print(string S);
template <typename T> void print(vector<vector<T>> &F);

inline void Yes(bool f);

#define equals(a, b) (fabs((a) - (b)) < EPS)

const double EPS = 1e-10;
const double PI = asinl(1) * 2;

struct Point {
    double x, y;
    Point() {}
    Point(double x, double y) : x(x), y(y) {}
    Point operator+(Point p) { return Point(x + p.x, y + p.y); }
    Point operator-(Point p) { return Point(x - p.x, y - p.y); }
    Point operator*(double k) { return Point(x * k, y * k); }
    Point operator/(double k) { return Point(x / k, y / k); }
    double norm() { return x * x + y * y; }
    double abs() { return sqrt(norm()); }

    bool operator<(const Point &p) const {
        return x != p.x ? x < p.x : y < p.y;
        // grid-point only
        // return !equals(x,p.x)?x<p.x:!equals(y,p.y)?y<p.y:0;
    }

    bool operator==(const Point &p) const {
        return fabs(x - p.x) < EPS and fabs(y - p.y) < EPS;
    }
};

bool sort_x(Point a, Point b) { return a.x != b.x ? a.x < b.x : a.y < b.y; }

bool sort_y(Point a, Point b) { return a.y != b.y ? a.y < b.y : a.x < b.x; }

typedef Point Vector;
typedef vector<Point> Polygon;

struct Segment {
    Point p1, p2;
    Segment() {}
    Segment(Point p1, Point p2) : p1(p1), p2(p2) {}
};
typedef Segment Line;

struct Circle {
    Point c;
    double r;
    Circle() {}
    Circle(Point c, double r) : c(c), r(r) {}
};

double norm(Vector a) { return a.x * a.x + a.y * a.y; }

double abs(Vector a) { return sqrt(norm(a)); }

double dot(Vector a, Vector b) { return a.x * b.x + a.y * b.y; }

double cross(Vector a, Vector b) { return a.x * b.y - a.y * b.x; }

Point orth(Point p) { return Point(-p.y, p.x); }

bool isOrthogonal(Vector a, Vector b) { return equals(dot(a, b), 0.0); }

bool isOrthogonal(Point a1, Point a2, Point b1, Point b2) {
    return isOrthogonal(a1 - a2, b1 - b2);
}

bool isOrthogonal(Segment s1, Segment s2) {
    return equals(dot(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
}

bool isParallel(Vector a, Vector b) { return equals(cross(a, b), 0.0); }

bool isParallel(Point a1, Point a2, Point b1, Point b2) {
    return isParallel(a1 - a2, b1 - b2);
}

bool isParallel(Segment s1, Segment s2) {
    return equals(cross(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
}

Point project(Segment s, Point p) {
    Vector base = s.p2 - s.p1;
    double r = dot(p - s.p1, base) / norm(base);
    return s.p1 + base * r;
}

Point reflect(Segment s, Point p) { return p + (project(s, p) - p) * 2.0; }

double arg(Vector p) { return atan2(p.y, p.x); }

Vector polar(double a, double r) { return Point(cos(r) * a, sin(r) * a); }

// COUNTER CLOCKWISE
static const int CCW_COUNTER_CLOCKWISE = 1;
static const int CCW_CLOCKWISE = -1;
static const int CCW_ONLINE_BACK = 2;
static const int CCW_ONLINE_FRONT = -2;
static const int CCW_ON_SEGMENT = 0;

int ccw(Point p0, Point p1, Point p2) {
    Vector a = p1 - p0;
    Vector b = p2 - p0;
    if (cross(a, b) > EPS)
        return CCW_COUNTER_CLOCKWISE;
    if (cross(a, b) < -EPS)
        return CCW_CLOCKWISE;
    if (dot(a, b) < -EPS)
        return CCW_ONLINE_BACK;
    if (a.norm() < b.norm())
        return CCW_ONLINE_FRONT;
    return CCW_ON_SEGMENT;
}

bool intersectSS(Point p1, Point p2, Point p3, Point p4) {
    return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 and
            ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);
}

bool intersectSS(Segment s1, Segment s2) {
    return intersectSS(s1.p1, s1.p2, s2.p1, s2.p2);
}

bool intersectPS(Polygon p, Segment l) {
    int n = p.size();
    for (int i = 0; i < n; ++i)
        if (intersectSS(Segment(p[i], p[(i + 1) % n]), l))
            return 1;
    return 0;
}

double getDistanceLP(Line l, Point p) {
    return fabs(cross(l.p2 - l.p1, p - l.p1) / abs(l.p2 - l.p1));
}

double getDistanceSP(Segment s, Point p) {
    if (dot(s.p2 - s.p1, p - s.p1) < 0.0)
        return abs(p - s.p1);
    if (dot(s.p1 - s.p2, p - s.p2) < 0.0)
        return abs(p - s.p2);
    return getDistanceLP(s, p);
}

double getDistanceSS(Segment s1, Segment s2) {
    if (intersectSS(s1, s2))
        return 0.0;
    return min(min(getDistanceSP(s1, s2.p1), getDistanceSP(s1, s2.p2)),
               min(getDistanceSP(s2, s1.p1), getDistanceSP(s2, s1.p2)));
}

// intercsect of circles
static const int ICC_SEPERATE = 4;
static const int ICC_CIRCUMSCRIBE = 3;
static const int ICC_INTERSECT = 2;
static const int ICC_INSCRIBE = 1;
static const int ICC_CONTAIN = 0;

int intersectCC(Circle c1, Circle c2) {
    if (c1.r < c2.r)
        swap(c1, c2);
    double d = abs(c1.c - c2.c);
    double r = c1.r + c2.r;
    if (equals(d, r))
        return ICC_CIRCUMSCRIBE;
    if (d > r)
        return ICC_SEPERATE;
    if (equals(d + c2.r, c1.r))
        return ICC_INSCRIBE;
    if (d + c2.r < c1.r)
        return ICC_CONTAIN;
    return ICC_INTERSECT;
}

bool intersectSC(Segment s, Circle c) { return getDistanceSP(s, c.c) <= c.r; }

int intersectCS(Circle c, Segment s) {
    if (norm(project(s, c.c) - c.c) - c.r * c.r > EPS)
        return 0;
    double d1 = abs(c.c - s.p1), d2 = abs(c.c - s.p2);
    if (d1 < c.r + EPS and d2 < c.r + EPS)
        return 0;
    if ((d1 < c.r - EPS and d2 > c.r + EPS) or
        (d1 > c.r + EPS and d2 < c.r - EPS))
        return 1;
    Point h = project(s, c.c);
    if (dot(s.p1 - h, s.p2 - h) < 0)
        return 2;
    return 0;
}

Point getCrossPointSS(Segment s1, Segment s2) {
    for (int k = 0; k < 2; ++k) {
        if (getDistanceSP(s1, s2.p1) < EPS)
            return s2.p1;
        if (getDistanceSP(s1, s2.p2) < EPS)
            return s2.p2;
        swap(s1, s2);
    }
    Vector base = s2.p2 - s2.p1;
    double d1 = fabs(cross(base, s1.p1 - s2.p1));
    double d2 = fabs(cross(base, s1.p2 - s2.p1));
    double t = d1 / (d1 + d2);
    return s1.p1 + (s1.p2 - s1.p1) * t;
}

Point getCrossPointLL(Line l1, Line l2) {
    double a = cross(l1.p2 - l1.p1, l2.p2 - l2.p1);
    double b = cross(l1.p2 - l1.p1, l1.p2 - l2.p1);
    if (fabs(a) < EPS and fabs(b) < EPS)
        return l2.p1;
    return l2.p1 + (l2.p2 - l2.p1) * (b / a);
}

Polygon getCrossPointCL(Circle c, Line l) {
    Polygon ps;
    Point pr = project(l, c.c);
    Vector e = (l.p2 - l.p1) / abs(l.p2 - l.p1);
    if (equals(getDistanceLP(l, c.c), c.r)) {
        ps.emplace_back(pr);
        return ps;
    }
    double base = sqrt(c.r * c.r - norm(pr - c.c));
    ps.emplace_back(pr + e * base);
    ps.emplace_back(pr - e * base);
    return ps;
}

Polygon getCrossPointCS(Circle c, Segment s) {
    Line l(s);
    Polygon res = getCrossPointCL(c, l);
    if (intersectCS(c, s) == 2)
        return res;
    if (res.size() > 1u) {
        if (dot(l.p1 - res[0], l.p2 - res[0]) > 0)
            swap(res[0], res[1]);
        res.pop_back();
    }
    return res;
}

Polygon getCrossPointCC(Circle c1, Circle c2) {
    Polygon p(2);
    double d = abs(c1.c - c2.c);
    double a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
    double t = arg(c2.c - c1.c);
    p[0] = c1.c + polar(c1.r, t + a);
    p[1] = c1.c + polar(c1.r, t - a);
    return p;
}

// IN:2 ON:1 OUT:0
int contains(Polygon g, Point p) {
    int n = g.size();
    bool x = false;
    for (int i = 0; i < n; ++i) {
        Point a = g[i] - p, b = g[(i + 1) % n] - p;
        if (fabs(cross(a, b)) < EPS and dot(a, b) < EPS)
            return 1;
        if (a.y > b.y)
            swap(a, b);
        if (a.y < EPS and EPS < b.y and cross(a, b) > EPS)
            x = !x;
    }
    return (x ? 2 : 0);
}

// BEGIN IGNORE
Polygon andrewScan(Polygon s) {
    Polygon u, l;
    if (s.size() < 3)
        return s;
    sort(s.begin(), s.end());
    u.push_back(s[0]);
    u.push_back(s[1]);
    l.push_back(s[s.size() - 1]);
    l.push_back(s[s.size() - 2]);
    for (int i = 2; i < (int)s.size(); ++i) {
        for (int n = u.size();
             n >= 2 and ccw(u[n - 2], u[n - 1], s[i]) != CCW_CLOCKWISE; n--) {
            u.pop_back();
        }
        u.push_back(s[i]);
    }
    for (int i = s.size() - 3; i >= 0; i--) {
        for (int n = l.size();
             n >= 2 and ccw(l[n - 2], l[n - 1], s[i]) != CCW_CLOCKWISE; n--) {
            l.pop_back();
        }
        l.push_back(s[i]);
    }
    reverse(l.begin(), l.end());
    for (int i = u.size() - 2; i >= 1; i--)
        l.push_back(u[i]);
    return l;
}
// END IGNORE

Polygon convex_hull(Polygon ps) {
    int n = ps.size();
    sort(ps.begin(), ps.end(), sort_y);
    int k = 0;
    Polygon qs(n * 2);
    for (int i = 0; i < n; ++i) {
        while (k > 1 and cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < 0)
            k--;
        qs[k++] = ps[i];
    }
    for (int i = n - 2, t = k; i >= 0; i--) {
        while (k > t and cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < 0)
            k--;
        qs[k++] = ps[i];
    }
    qs.resize(k - 1);
    return qs;
}

double diameter(Polygon s) {
    Polygon p = s;
    int n = p.size();
    if (n == 2)
        return abs(p[0] - p[1]);
    int i = 0, j = 0;
    for (int k = 0; k < n; ++k) {
        if (p[i] < p[k])
            i = k;
        if (!(p[j] < p[k]))
            j = k;
    }
    double res = 0;
    int si = i, sj = j;
    while (i != sj or j != si) {
        res = max(res, abs(p[i] - p[j]));
        if (cross(p[(i + 1) % n] - p[i], p[(j + 1) % n] - p[j]) < 0.0) {
            i = (i + 1) % n;
        } else {
            j = (j + 1) % n;
        }
    }
    return res;
}

bool isConvex(Polygon p) {
    bool f = 1;
    int n = p.size();
    for (int i = 0; i < n; ++i) {
        int t = ccw(p[(i + n - 1) % n], p[i], p[(i + 1) % n]);
        f &= t != CCW_CLOCKWISE;
    }
    return f;
}

double area(Polygon s) {
    double res = 0;
    for (int i = 0; i < (int)s.size(); ++i) {
        res += cross(s[i], s[(i + 1) % s.size()]) / 2.0;
    }
    return res;
}

double area(Circle c1, Circle c2) {
    double d = abs(c1.c - c2.c);
    if (c1.r + c2.r <= d + EPS)
        return 0;
    if (d <= fabs(c1.r - c2.r)) {
        double r = min(c1.r, c2.r);
        return PI * r * r;
    }
    double res = 0;
    for (int k = 0; k < 2; ++k) {
        double rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d * c1.r);
        double th = acosl(rc) * 2;
        res += (th - sinl(th)) * c1.r * c1.r / 2;
        swap(c1, c2);
    }
    return res;
}

Polygon convexCut(Polygon p, Line l) {
    Polygon q;
    for (int i = 0; i < (int)p.size(); ++i) {
        Point a = p[i], b = p[(i + 1) % p.size()];
        if (ccw(l.p1, l.p2, a) != -1)
            q.push_back(a);
        if (ccw(l.p1, l.p2, a) * ccw(l.p1, l.p2, b) < 0)
            q.push_back(getCrossPointLL(Line(a, b), l));
    }
    return q;
}

Line bisector(Point p1, Point p2) {
    Circle c1 = Circle(p1, abs(p1 - p2)), c2 = Circle(p2, abs(p1 - p2));
    Polygon p = getCrossPointCC(c1, c2);
    if (cross(p2 - p1, p[0] - p1) > 0)
        swap(p[0], p[1]);
    return Line(p[0], p[1]);
}

Vector translate(Vector v, double theta) {
    Vector res;
    res.x = cos(theta) * v.x - sin(theta) * v.y;
    res.y = sin(theta) * v.x + cos(theta) * v.y;
    return res;
}

vector<Line> corner(Line l1, Line l2) {
    vector<Line> res;
    if (isParallel(l1, l2)) {
        double d = getDistanceLP(l1, l2.p1) / 2.0;
        Vector v1 = l1.p2 - l1.p1;
        v1 = v1 / v1.abs() * d;
        Point p = l2.p1 + translate(v1, 90.0 * (PI / 180.0));
        double d1 = getDistanceLP(l1, p);
        double d2 = getDistanceLP(l2, p);
        if (fabs(d1 - d2) > d) {
            p = l2.p1 + translate(v1, -90.0 * (PI / 180.0));
        }
        res.push_back(Line(p, p + v1));
    } else {
        Point p = getCrossPointLL(l1, l2);
        Vector v1 = l1.p2 - l1.p1, v2 = l2.p2 - l2.p1;
        v1 = v1 / v1.abs();
        v2 = v2 / v2.abs();
        res.push_back(Line(p, p + (v1 + v2)));
        res.push_back(Line(p, p + translate(v1 + v2, 90.0 * (PI / 180.0))));
    }
    return res;
}

Polygon tangent(Circle c1, Point p2) {
    Circle c2 = Circle(p2, sqrt(norm(c1.c - p2) - c1.r * c1.r));
    Polygon p = getCrossPointCC(c1, c2);
    sort(p.begin(), p.end());
    return p;
}

vector<Line> tangent(Circle c1, Circle c2) {
    vector<Line> ls;
    if (c1.r < c2.r)
        swap(c1, c2);
    double g = norm(c1.c - c2.c);
    if (equals(g, 0))
        return ls;
    Point u = (c2.c - c1.c) / sqrt(g);
    Point v = orth(u);
    for (int s = 1; s >= -1; s -= 2) {
        double h = (c1.r + s * c2.r) / sqrt(g);
        if (equals(1 - h * h, 0)) {
            ls.emplace_back(c1.c + u * c1.r, c1.c + (u + v) * c1.r);
        } else if (1 - h * h > 0) {
            Point uu = u * h, vv = v * sqrt(1 - h * h);
            ls.emplace_back(c1.c + (uu + vv) * c1.r,
                            c2.c - (uu + vv) * c2.r * s);
            ls.emplace_back(c1.c + (uu - vv) * c1.r,
                            c2.c - (uu - vv) * c2.r * s);
        }
    }

    return ls;
}

double closest_pair(Polygon &a, int l = 0, int r = -1) {
    if (r < 0) {
        r = a.size();
        sort(a.begin(), a.end(), sort_x);
    }
    if (r - l <= 1)
        return abs(a[0] - a[1]);
    int m = (l + r) >> 1;
    double x = a[m].x;
    double d = min(closest_pair(a, l, m), closest_pair(a, m, r));
    inplace_merge(a.begin() + l, a.begin() + m, a.begin() + r, sort_y);

    Polygon b;
    for (int i = l; i < r; ++i) {
        if (fabs(a[i].x - x) >= d)
            continue;
        for (int j = 0; j < (int)b.size(); ++j) {
            double dy = a[i].y - next(b.rbegin(), j)->y;
            if (dy >= d)
                break;
            d = min(d, abs(a[i] - *next(b.rbegin(), j)));
        }
        b.emplace_back(a[i]);
    }
    return d;
}

vector<vector<int>> segmentArrangement(vector<Segment> &ss, Polygon &ps) {
    int n = ss.size();
    for (int i = 0; i < n; ++i) {
        ps.emplace_back(ss[i].p1);
        ps.emplace_back(ss[i].p2);
        for (int j = i + 1; j < n; ++j)
            if (intersectSS(ss[i], ss[j]))
                ps.emplace_back(getCrossPointSS(ss[i], ss[j]));
    }
    sort(ps.begin(), ps.end());
    ps.erase(unique(ps.begin(), ps.end()), ps.end());

    vector<vector<int>> G(ps.size());
    for (int i = 0; i < n; ++i) {
        vector<pair<double, int>> ls;
        for (int j = 0; j < (int)ps.size(); ++j)
            if (getDistanceSP(ss[i], ps[j]) < EPS)
                ls.emplace_back(make_pair(norm(ss[i].p1 - ps[j]), j));

        sort(ls.begin(), ls.end());
        for (int j = 0; j + 1 < (int)ls.size(); ++j) {
            int a = ls[j].second, b = ls[j + 1].second;
            G[a].emplace_back(b);
            G[b].emplace_back(a);
        }
    }
    for (auto &v : G) {
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
    }
    return G;
}

struct EndPoint {
    Point p;
    int seg, st;
    EndPoint() {}
    EndPoint(Point p, int seg, int st) : p(p), seg(seg), st(st) {}
    bool operator<(const EndPoint &ep) const {
        if (p.y == ep.p.y)
            return st < ep.st;
        return p.y < ep.p.y;
    }
};

int manhattan_intersection(vector<Segment> ss, const int INF) {
    const int BTM = 0;
    const int LFT = 1;
    const int RGH = 2;
    const int TOP = 3;

    int n = ss.size();
    vector<EndPoint> ep;
    for (int i = 0; i < n; ++i) {
        if (ss[i].p1.y == ss[i].p2.y) {
            if (ss[i].p1.x > ss[i].p2.x)
                swap(ss[i].p1, ss[i].p2);
            ep.emplace_back(ss[i].p1, i, LFT);
            ep.emplace_back(ss[i].p2, i, RGH);
        } else {
            if (ss[i].p1.y > ss[i].p2.y)
                swap(ss[i].p1, ss[i].p2);
            ep.emplace_back(ss[i].p1, i, BTM);
            ep.emplace_back(ss[i].p2, i, TOP);
        }
    }
    sort(ep.begin(), ep.end());

    set<int> bt;
    bt.insert(INF);

    int cnt = 0;
    for (int i = 0; i < n * 2; ++i) {
        if (ep[i].st == TOP) {
            bt.erase(ep[i].p.x);
        } else if (ep[i].st == BTM) {
            bt.emplace(ep[i].p.x);
        } else if (ep[i].st == LFT) {
            auto b = bt.lower_bound(ss[ep[i].seg].p1.x);
            auto e = bt.upper_bound(ss[ep[i].seg].p2.x);
            cnt += distance(b, e);
        }
    }

    return cnt;
}

double area(Polygon ps, Circle c) {
    if (ps.size() < 3u)
        return 0;
    function<double(Circle, Point, Point)> dfs = [&](Circle c, Point a,
                                                     Point b) {
        Vector va = c.c - a, vb = c.c - b;
        double f = cross(va, vb), res = 0;
        if (equals(f, 0.0))
            return res;
        if (max(abs(va), abs(vb)) < c.r + EPS)
            return f;
        Vector d(dot(va, vb), cross(va, vb));
        if (getDistanceSP(Segment(a, b), c.c) > c.r - EPS)
            return c.r * c.r * atan2(d.y, d.x);
        auto u = getCrossPointCS(c, Segment(a, b));
        if (u.empty())
            return res;
        if (u.size() > 1u and dot(u[1] - u[0], a - u[0]) > 0)
            swap(u[0], u[1]);
        u.emplace(u.begin(), a);
        u.emplace_back(b);
        for (int i = 1; i < (int)u.size(); ++i)
            res += dfs(c, u[i - 1], u[i]);
        return res;
    };
    double res = 0;
    for (int i = 0; i < (int)ps.size(); ++i)
        res += dfs(c, ps[i], ps[(i + 1) % ps.size()]);
    return res / 2;
}

Point get_t_point(vector<Point> &Ps, vector<double> &Ds, double t) {
    int N = Ps.size();
    auto ite = upper_bound(all(Ds), t);
    int idx = distance(Ds.begin(), ite) - 1;

    double t0 = t - Ds[idx];
    Point P0 = Ps[idx], P1 = Ps[(idx + 1) % N];
    Vector V = P1 - P0;
    Point P = P0 + V * t0 / abs(V);

    return P;
}

double get_area(Point P1, Point P2, Point P3) {
    return cross(P2 - P1, P3 - P1) / 2.0;
}

///////////////////ここから//////////////////////
bool solve() {
    int N, KP, KQ, KR;
    cin >> N >> KP >> KQ >> KR;
    KP--;
    KQ--;
    KR--;
    if (N == 0) {
        return false;
    }
    vector<pii> XY(N);
    for (int i = 0; i < N; i++) {
        cin >> XY[i].first >> XY[i].second;
    }

    vector<double> DP, DQ, DR;
    vector<Point> PP, PQ, PR;

    vector<double> Times;

    double dis = 0;
    for (int i = 0; i < N + 1; i++) {
        int idx = (i + KP) % N;
        auto [x, y] = XY[idx];

        if (i) {
            dis += abs(Point(x, y) - PP.back());
        }
        Times.push_back(dis);
        DP.push_back(dis);
        PP.emplace_back(x, y);
    }
    dis = 0;
    for (int i = 0; i < N + 1; i++) {
        int idx = (i + KQ) % N;
        auto [x, y] = XY[idx];
        if (i) {
            dis += abs(Point(x, y) - PQ.back());
        }
        Times.push_back(dis);
        DQ.push_back(dis);
        PQ.emplace_back(x, y);
    }
    dis = 0;
    for (int i = 0; i < N + 1; i++) {
        int idx = (i + KR) % N;
        auto [x, y] = XY[idx];
        if (i) {
            dis += abs(Point(x, y) - PR.back());
        }
        Times.push_back(dis);
        DR.push_back(dis);
        PR.emplace_back(x, y);
    }

    sort(all(Times));
    Times.erase(unique(all(Times)), Times.end());

    auto area = [&](double t) {
        Point P1 = get_t_point(PP, DP, t);
        Point P2 = get_t_point(PQ, DQ, t);
        Point P3 = get_t_point(PR, DR, t);
        return get_area(P1,P2,P3);
    };
    double ans=INF64;
    for (int i = 0; i < Times.size() - 1; i++) {
        double t0 = Times[i], t1 = Times[i + 1];
        while (t1 - t0 > 1e-9) {
            double tl = t0 + (t1 - t0) / 3;
            double tr = tl + (t1 - t0) / 3;
            double vl = area(tl), vr = area(tr);
            if (vl < vr) {
                t1=tr;
            } else {
                t0=tl;
            }
        }
        chmin(ans,area(t0));
    }
    cout << fixed << setprecision(10);
    cout<<ans<<endl;

    return true;
}

int main() {
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    while (solve())
        ;
}

////////////////////print/////////////////////////
// 1次元ベクトルを出力する
template <typename T> void print(vector<T> A) {
    if (A.size() == 0) {
        return;
    }
    for (size_t i = 0; i < A.size() - 1; i++) {
        cout << A[i] << ' ';
    }
    cout << A[A.size() - 1] << endl;
    return;
}

// 2次元ベクトルを出力する
template <typename T> void print(vector<vector<T>> &F) {
    for (size_t i = 0; i < F.size(); i++) {
        for (size_t j = 0; j < F[i].size(); j++) {
            cout << F[i][j];
            if (j < F[i].size() - 1) {
                cout << ' ';
            }
        }
        cout << endl;
    }
}

// 空白行を出力するprint
void print() { cout << endl; }

// 数値・文字列を空白区切りで出力する. print(a,b)など
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    cout << head;
    if (sizeof...(tail) != 0)
        cout << " ";
    print(forward<Tail>(tail)...);
}

void print(string S) { cout << S << endl; }

//////////////出力関連

inline void Yes(bool f) {
    if (f) {
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
}
accuracy: 1
time_ms: 80
memory_kb: 3968
final_rank: 17

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;

// 数値型
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using P = pair<int,int>;
using Pll = pair<ll, ll>;
using Pli = pair<ll, int>;
using Pil = pair<int, ll>;

// vector関連
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
template<typename T>
using vc = vector<T>;
template<typename T>
using vvc = vector<vc<T>>;
template<typename T>
using vvvc = vector<vvc<T>>;
template<typename T>
using vvvvc = vector<vvvc<T>>;

// priority_queue
template<typename T>
using pq = priority_queue<T>;
template<typename T>
using pqg = priority_queue<T, vc<T>, greater<T>>;

#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define FOR(i, a, b) for(int i = a; i < (int)(b); i++)
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define MIN(vec) *min_element(vec)
#define MAX(vec) *max_element(vec)
#define next_perm(vec) (vec).begin(), (vec).end()
#define UNIQUE(vec) vec.erase(unique(vec.begin(), vec.end()), vec.end())
#define el "\n"
#define Yes cout << "Yes" << el
#define No cout << "No" << el
#define YES cout << "YES" << el
#define NO cout << "NO" << el
#define EPS 1e-8
#define Equal(a, b) (fabs((a)-(b)) < EPS) 
#define dbg(x) cerr << #x << "=" << x << el 

// 定数
const string abc = "abcdefghijklmnopqrstuvwxyz";
const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
constexpr int INF = 1001001001;
constexpr ll LINF = 1001001001001001001ll;
constexpr int DX[] = {1, 0, -1, 0};
constexpr int DY[] = {0, 1, 0, -1};
constexpr int DX8[] = {1, 0, -1, 0, 1, 1, -1, -1};
constexpr int DY8[] = {0, 1, 0, -1, 1, -1, 1, -1};

template<typename T1, typename T2>
ostream &operator<< (ostream &os, pair<T1, T2> p) {
    os << "{" << p.first << "," << p.second << "}";
    return os;
}
template<typename T>
ostream &operator<< (ostream &os, vc<T> &vec) {
    int sz = vec.size();
    rep(i, sz){
        os << vec[i] << (i==sz-1?"":" ");
    }
    return os;
}

template<typename T1, typename T2>
istream &operator>> (istream &is, pair<T1, T2> &p) {
    is >> p.first >> p.second;
    return is;
}
template<typename T>
istream &operator>> (istream &is, vc<T> &vec) {
    int sz = vec.size();
    rep(i, sz) { is >> vec[i]; }
    return is;
}
/// @brief aとｂの最大値をaに格納。更新があったかbool値を返す
/// @tparam T1 
/// @tparam T2 
/// @param a 
/// @param b 
/// @return bool
template<typename T1, typename T2>
inline bool chmax(T1 &a, T2 b){
    bool ret = a<b;
    if(ret) a = b;
    return ret;
}

/// @brief aとｂの最小値をaに格納。更新があったかbool値を返す
/// @tparam T1 
/// @tparam T2 
/// @param a 
/// @param b 
/// @return bool
template<typename T1, typename T2>
inline bool chmin(T1 &a, T2 b){
    bool ret = a>b;
    if(ret) {a = b;}
    return ret;
}

inline void YesNo(bool flag){
    if(flag) {Yes;}
    else {No;}
    return;
}

inline void YESNO(bool flag){
    if(flag) {YES;}
    else {NO;}
    return;
}

inline bool outof(ll x, ll xlim){
    return (x<0 || x>=xlim);
}

template<typename T>
inline T sqnorm(T x, T y){
    return x*x+y*y;
}

/// @brief char->int
/// @param c 
/// @return int
inline int ctoi(char c){
    return c-'0';
}

/// @brief xを素因数分解
/// @param x 
/// @return vector<Pli>, 素因数の昇順に {p, cnt}
vector<Pli> prime_fact(ll x){
    vector<Pli> ret;
    for(ll i=2; i*i<=x; i++){
        if(x%i == 0){
            ret.emplace_back(i, 0);
            while(x%i == 0){
                ret.back().second++;
                x /= i;
            }
        }
    }
    if(x != 1) ret.emplace_back(x, 1);
    return ret;
}

/// @brief xの約数列挙
/// @param x 
/// @return vll, 約数の昇順
vll divisor_enum(ll x){
    vector<ll> ret;
    for(ll i=1; i*i<=x; i++){
        if(x%i == 0){
            ret.push_back(x/i);
            ret.push_back(i);
        }
    }
    sort(all(ret));
    UNIQUE(ret);
    return ret;
}

/// @brief 繰り返し二乗法。
/// @tparam T 
/// @param x 
/// @param k 
/// @param op 
/// @param e 
/// @return 
template<typename T>
T pow_t(T x, ll k, T (*op)(T, T), T (*e)()){
    T ret = e();
    while(k){
        if(k&1) ret *= x;
        x *= x;
        k >>= 1;
    }
    return ret;
}

ll powll(ll x, ll k){
    return pow_t<ll>(x, k, [](ll a, ll b) -> ll{return a*b;}, []() -> ll{return 1;});
}

inline int pop_cnt(ll x) { return __builtin_popcountll(x); }
inline int top_bit(ll x) { return (x==0?-1:63-__builtin_clzll(x));}

void main2();

int main(){
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    main2();
}
struct Point{
    int x, y;
};
bool solve(){
    int n;
    cin >> n;
    if(n == 0) return false;
    vi Ks(3);
    cin >> Ks[0] >> Ks[1] >> Ks[2];
    vector<Point> ps(2*n);
    vector<double> cumdist(2*n+1, 0);
    vector<vector<double>> cumd2(3);
    rep(i, n){
        cin >> ps[i].x >> ps[i].y;
        ps[i+n] = ps[i];
    }
    rep(i, 3) Ks[i]--;
    auto dist = [](Point a, Point b) -> double{
        double dx = a.x - b.x;
        double dy = a.y - b.y;
        return sqrt(dx*dx + dy*dy);
    };
    rep(i, 2*n){
        cumdist[i+1] = cumdist[i] + dist(ps[i], ps[(i+1)%(2*n)]);
    }
    rep(i, 3){
        cumd2[i] = vector<double>(cumdist.begin() + Ks[i], cumdist.begin() + Ks[i] + n+1);
        rep(j, n) cumd2[i][j+1] -= cumd2[i][0];
        cumd2[i][0] = 0;
    }
    
    auto calcPos = [&](int v, double t) -> pair<double, double>{
        double d = dist(ps[v], ps[v+1]);
        double dx = ps[v+1].x - ps[v].x;
        double dy = ps[v+1].y - ps[v].y;
        return pair(ps[v].x + dx/d*t, ps[v].y + dy/d*t);
    };
    auto calcPos2 = [&](int id, double t) -> pair<double, double>{
        auto idx = upper_bound(all(cumd2[id]), t) - cumd2[id].begin() - 1;
        chmax(idx, 0);
        return calcPos(idx + Ks[id], t - cumd2[id][idx]);
    };
    auto f = [&](double t) -> double{
        vector<pair<double, double>> pss(3);
        rep(i, 3) pss[i] = calcPos2(i, t);
        pair<double, double> a = {pss[1].first - pss[0].first, pss[1].second - pss[0].second};
        pair<double, double> b = {pss[2].first - pss[0].first, pss[2].second - pss[0].second};
        return abs(a.first*b.second - a.second*b.first)/2;
    };
    vector<double> events;
    double ans = 1e18;
    rep(i, n){
        // p, q, rそれぞれについてiにいるとき
        rep(k, 3){
            double t;
            if(Ks[k] <= i) t = cumdist[i+1] - cumdist[Ks[k]];
            else t = cumdist[i+1+n] - cumdist[Ks[k]];
            events.push_back(t);
        }
    }
    sort(all(events));
    events.push_back(cumdist[n]);
    rep(i, events.size()-1){
        double lo = events[i], hi = events[i+1];
        rep(j, 100){
            double mid1 = (hi + lo*2)/3;
            double mid2 = (hi*2 + lo)/3;
            if(f(mid1) < f(mid2)) hi = mid2;
            else lo = mid1;
        }
        chmin(ans, f(lo));
    }
    
    cout << fixed << setprecision(16) << ans << el;
    return true;
}

void main2(){
    while(solve()){
        ;
    }
}
accuracy: 1
time_ms: 200
memory_kb: 3840
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define loop(n) for (int tjh = 0; tjh < (int)(n); tjh++)
constexpr double ma = 1e100;
signed main() {
    cin.tie(0)->sync_with_stdio(0);
    cout << fixed << setprecision(16);
    vector<double> x, y;
    int N;
    array<int, 3> K;
    for (; cin >> N >> K[0] >> K[1] >> K[2], N;) {
        rep(i, 3)-- K[i];
        x.resize(N * 2);
        y.resize(N * 2);
        rep(i, N) cin >> x[i] >> y[i];
        rep(i, N) {
            x[i + N] = x[i];
            y[i + N] = y[i];
        }
        vector<double> dx(2 * N - 1), dy(2 * N - 1);
        rep(i, 2 * N - 2) {
            dx[i] = x[i + 1] - x[i];
            dy[i] = y[i + 1] - y[i];
        }
        vector<double> dist(2 * N - 1);
        rep(i, 2 * N - 2) dist[i] = hypot(dx[i], dy[i]);
        array<vector<double>, 3> D{};
        rep(i, 3) D[i].resize(N + 1);
        rep(i, 3) rep(j, N - 1) D[i][j + 1] = D[i][j] + dist[K[i] + j];
        D[0][N] = D[0][N - 1] + dist[K[0] + N - 1];
        D[1][N] = D[0][N];
        D[2][N] = D[0][N];
        array<int, 3> pos = {1, 1, 1};
        double res = ma;
        double l = 0;
        loop(3 * N - 2) {
            int nxt;
            double r;
            if (D[0][pos[0]] <= D[1][pos[1]] && D[0][pos[0]] <= D[2][pos[2]]) {
                nxt = 0;
                r = D[0][pos[0]];
            } else if (D[1][pos[1]] <= D[2][pos[2]] &&
                       D[1][pos[1]] <= D[0][pos[0]]) {
                nxt = 1;
                r = D[1][pos[1]];
            } else {
                nxt = 2;
                r = D[2][pos[2]];
            }
            const double maxt = r - l;
            array<array<double, 2>, 3> S;
            rep(i, 3) {
                S[i] = {x[K[i] + pos[i] - 1] + dx[K[i] + pos[i] - 1] *
                                                   (l - D[i][pos[i] - 1]) /
                                                   dist[K[i] + pos[i] - 1],
                        y[K[i] + pos[i] - 1] + dy[K[i] + pos[i] - 1] *
                                                   (l - D[i][pos[i] - 1]) /
                                                   dist[K[i] + pos[i] - 1]};
            }
            array<double, 2> L = {S[1][0] - S[0][0], S[1][1] - S[0][1]};
            array<double, 2> M = {S[2][0] - S[0][0], S[2][1] - S[0][1]};
            array<double, 2> p = {
                dx[K[1] + pos[1] - 1] / dist[K[1] + pos[1] - 1] -
                    dx[K[0] + pos[0] - 1] / dist[K[0] + pos[0] - 1],
                dy[K[1] + pos[1] - 1] / dist[K[1] + pos[1] - 1] -
                    dy[K[0] + pos[0] - 1] / dist[K[0] + pos[0] - 1]};
            array<double, 2> q = {
                dx[K[2] + pos[2] - 1] / dist[K[2] + pos[2] - 1] -
                    dx[K[0] + pos[0] - 1] / dist[K[0] + pos[0] - 1],
                dy[K[2] + pos[2] - 1] / dist[K[2] + pos[2] - 1] -
                    dy[K[0] + pos[0] - 1] / dist[K[0] + pos[0] - 1]};
            auto f = [&](double v) -> double {
                // cout << "v: " << v << '\n';
                const double re0 = (L[0] + v * p[0]) * (M[1] + v * q[1]) -
                                   (L[1] + v * p[1]) * (M[0] + v * q[0]);
                // cout << "ans: " << re0 << '\n';
                return re0;
            };
            if (p[0] * q[1] - p[1] * q[0] <= (double)0) {
                double l0 = f(0);
                if (l0 < res) res = l0;
                double r0 = f(maxt);
                if (r0 < res) res = r0;
            } else {
                double l = 0.0, r = maxt;
                for (int rap = 0; rap < 64; ++rap) {
                    double nl = (l * 2 + r) / 3.0;
                    double nr = (l + 2 * r) / 3.0;
                    if (f(nl) >= f(nr)) {
                        l = nl;
                    } else {
                        r = nr;
                    }
                }
                double re0 = f(l);
                if (re0 < res) res = re0;
            }
            l = r;
            ++pos[nxt];
        }
        cout << res / 2.0 << '\n';
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3968
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (ll i = s; i < (ll)(t); i++)
#define rrep(i, s, t) for(ll i = (ll)(t) - 1; i >= (ll)(s); i--)
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)

#define TT template<typename T>
TT using vec = vector<T>;
template<class T1, class T2> bool chmin(T1 &x, T2 y) { return x > y ? (x = y, true) : false; }
template<class T1, class T2> bool chmax(T1 &x, T2 y) { return x < y ? (x = y, true) : false; }

struct io_setup {
    io_setup() {
        ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        cout << fixed << setprecision(15);
    }
} io_setup;

using Real = long double;

using Point = complex<long double>;
using Polygon = vector<Point>;

struct Line {
    Point a, b;
    Line(Point a, Point b) : a(a), b(b) {}
};

struct Segment : Line {
    Segment(Point a, Point b) : Line(a, b) {}
};

struct Circle {
    Point p;
    long double r;
    Circle(Point p, long double r) : p(p), r(r) {}
};

const long double pi = acos(-1.0);
const long double EPS = 1e-12;

// 内積
long double dot(const Point &a, const Point &b) {
    return (a.real() * b.real() + a.imag() * b.imag());
}

// 外積
long double cross(const Point &a, const Point &b) {
    return (a.real() * b.imag() - a.imag() * b.real());
}

// 直線 l に対する点 p の射影
Point projection(const Line l, const Point &p) {
    long double t = dot(p - l.a, l.b - l.a) / norm(l.b - l.a);
    return Point(l.a.real() + t * (l.b - l.a).real(), l.a.imag() + t * (l.b - l.a).imag());
}

// 直線 l に対する点 p の反射
Point reflection(const Line l, const Point &p) {
    long double t = dot(p - l.a, l.b - l.a) / norm(l.b - l.a);
    Point q(l.a.real() + t * (l.b - l.a).real(), l.a.imag() + t * (l.b - l.a).imag());
    return Point(2 * q.real() - p.real(), 2 * q.imag() - p.imag());
}

// p0 から p1 へ結んだベクトルから見た p2 の位置
int counter_clockwise(const Point &p2, Point p0, Point p1) {
    // 反時計回り
    if (cross(p1 - p0, p2 - p0) > EPS) {
        return 1;
    }
    // 時計回り
    if (cross(p1 - p0, p2 - p0) < -EPS) {
        return -1;
    }
    // p2, p0, p1 の順で同一直線上
    if (dot(p1 - p0, p2 - p0) < -EPS) {
        return 2;
    }
    // p0, p1, p2 の順で同一直線上
    if (dot(p1 - p0, p2 - p0) > norm(p1 - p0) + EPS) {
        return -2;
    }
    // p2 は p0 と p1 を結ぶ線分上
    return 0;
}

// 平行判定
bool is_parallel(const Line &l1, const Line &l2) {
    return (cross(l1.b - l1.a, l2.b - l2.a) == 0);
}

// 垂直判定
bool is_orthogonal(const Line &l1, const Line &l2) {
    return (dot(l1.b - l1.a, l2.b - l2.a) == 0);
}

// 線分と線分の交差判定
bool is_intersection(const Segment &s1, const Segment &s2) {
    return (counter_clockwise(s2.a, s1.a, s1.b) * counter_clockwise(s2.b, s1.a, s1.b) <= 0 && counter_clockwise(s1.a, s2.a, s2.b) * counter_clockwise(s1.b, s2.a, s2.b) <= 0);
}

// 線分と線分の交点の座標
Point cross_point(const Segment &s1, const Segment &s2) {
    long double d1 = cross(s1.a - s2.a, s1.b - s2.a);
    long double d2 = cross(s1.a - s1.b, s2.b - s2.a);
    if (abs(d1) < EPS && abs(d2) < EPS) {
        if (counter_clockwise(s1.a, s2.a, s2.b) == 0) return s1.a;
        else return s1.b;
    }
    return s2.a + (s2.b - s2.a) * (d1 / d2);
}

// 直線と線分の交差判定
bool is_intersection(const Line &l1, const Segment &s2) {
    return (counter_clockwise(s2.a, l1.a, l1.b) * counter_clockwise(s2.b, l1.a, l1.b) <= 0);
}

// 直線と線分の交点の座標
Point cross_point(const Line &s1, const Segment &s2) {
    long double d1 = cross(s1.a - s2.a, s1.b - s2.a);
    long double d2 = cross(s1.a - s1.b, s2.b - s2.a);
    if (abs(d1) < EPS && abs(d2) < EPS) {
        return s2.a;
    }
    return s2.a + (s2.b - s2.a) * (d1 / d2);
}

// 直線と点の距離
long double distance(const Line s, const Point &p) {
    long double t = dot(p - s.a, s.b - s.a) / norm(s.b - s.a);
    Point proj = Point(s.a.real() + t * (s.b - s.a).real(), s.a.imag() + t * (s.b - s.a).imag());
    return abs(p - proj);
}

// 線分と点の距離
long double distance(const Segment s, const Point &p) {
    long double t = dot(p - s.a, s.b - s.a) / norm(s.b - s.a);
    if (t > -EPS && t < 1 + EPS) {
        Point proj = Point(s.a.real() + t * (s.b - s.a).real(), s.a.imag() + t * (s.b - s.a).imag());
        return abs(p - proj);
    } else {
        return min(abs(p - s.a), abs(p - s.b));
    }
}

// 多角形の面積
long double area(const Polygon &poly) {
    long double ans = 0;
    int N = poly.size();
    for (int i = 0; i < N; i++) {
        ans += cross(poly[i], poly[(i + 1) % N]);
    }
    ans *= 0.5;
    return ans;
}

// 凸性判定
bool is_convex(const Polygon &poly) {
    int N = poly.size();
    for (int i = 0; i < N; i++) {
        if (counter_clockwise(poly[i], poly[(i + 1) % N], poly[(i + 2) % N]) == -1) return false;
    }
    return true;
}

// 多角形と点の包含関係
// 0 : 含まれない
// 1 : 辺の上にある
// 2 : 内部に含まれる
int is_contained(const Point p, const Polygon poly) {
    int N = poly.size();
    int cnt = 0;
    for (int i = 0; i < N; i++) {
        if (counter_clockwise(p, poly[i], poly[(i + 1) % N]) == 0) {
            return 1;
        }
        Point a = poly[i], b = poly[(i + 1) % N];
        if (a.imag() > b.imag()) swap(a, b);
        if (p.imag() < b.imag() + EPS && p.imag() > a.imag() + EPS && counter_clockwise(p, a, b) < 0) {
            cnt++;
        }
    }
    if (cnt % 2 == 0) return 0;
    else return 2;
}

// 凸包
Polygon convex_hull(vector<Point> &ps) {
    int N = ps.size();
    auto compare = [](const Point &p1, const Point &p2) {
        if (p1.real() != p2.real()) return p1.real() < p2.real();
        return p1.imag() < p2.imag();
    };
    sort(ps.begin(), ps.end(), compare);
    int k = 0;
    Polygon qs(2 * N);
    // 下側凸包
    for (int i = 0; i < N; i++) {
        while (k > 1 && cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < EPS) k--;
        qs[k++] = ps[i];
    }
    // 上側凸包
    for (int i = N - 2, t = k; i >= 0; i--) {
        while (k > t && cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < EPS) k--;
        qs[k++] = ps[i];
    }
    qs.resize(k - 1);
    return qs;
}

// 最も遠い２点の距離を求める
long double farest_pair(vector<Point> &ps) {
    Polygon poly = convex_hull(ps);
    long double ans = 0;
    for (int i = 0; i < (int)poly.size(); i++) {
        for (int j = 0; j < i; j++) {
            ans = max(ans, abs(poly[i] - poly[j]));
        }
    }
    return ans;
}

// 直線 l で凸多角形を切断し、左側の凸多角形を出力する
Polygon convex_cut(const Polygon &poly, const Line &l) {
    int N = poly.size();
    vector<Point> ps;
    for (int i = 0; i < N; i++) {
        if (cross(l.b - l.a, poly[i] - l.a) > -EPS) {
            ps.push_back(poly[i]);
        }
        if (is_intersection(l, Segment(poly[i], poly[(i + 1) % N]))) {
            ps.push_back(cross_point(l, Segment(poly[i], poly[(i + 1) % N])));
        }
    }
    if (ps.size() <= 0) return {};
    Polygon ch = convex_hull(ps);
    return ch;
}

// 最も近い２点の距離を求める
long double closest_pair(vector<Point> &ps) {
    auto dfs = [&](auto dfs, vector<Point> qs) -> long double {
        int N = qs.size();
        if (N <= 1) return 1e18;
        sort(qs.begin(), qs.end(), [](const Point &p1, const Point &p2) {
            if (abs(p1.real() - p2.real()) < EPS) return p1.imag() < p2.imag();
            return p1.real() < p2.real();
        });
        vector<Point> P1, P2;
        for (int i = 0; i < N / 2; i++) P1.push_back(qs[i]);
        for (int i = N / 2; i < N; i++) P2.push_back(qs[i]);
        long double d1 = dfs(dfs, P1), d2 = dfs(dfs, P2);
        long double d = min(d1, d2), ans = d;
        long double px = P1[N / 2 - 1].real(), py = P1[N / 2 - 1].imag();
        vector<pair<long double, int>> V;
        for (int i = 0; i < N; i++) {
            if (qs[i].real() < px - d - EPS || qs[i].real() > px + d + EPS) continue;
            V.push_back(make_pair(qs[i].imag(), i));
        }
        sort(V.begin(), V.end());
        int r = 0;
        for (int l = 0; l < (int)V.size(); l++) {
            r = max(r, l);
            while (r < (int)V.size() && V[r].first < V[l].first + d + EPS) {
                if (l != r) ans = min(ans, abs(qs[V[l].second] - qs[V[r].second]));
                r++;
            }
        }
        return ans;
    };
    return dfs(dfs, ps);
}

// 円の交差判定
int intersection_of_circle(const Circle &c1, const Circle &c2) {
    long double d = abs(c1.p - c2.p);
    // 分離
    if (d > c1.r + c2.r + EPS) {
        return 4;
    }
    // 外接
    if (abs(d - c1.r - c2.r) < EPS) {
        return 3;
    }
    // 交差
    if (d < c1.r + c2.r - EPS && d > abs(c1.r - c2.r) + EPS) {
        return 2;
    }
    // 内接
    if (abs(d - abs(c1.r - c2.r)) < EPS) {
        return 1;
    }
    // 包含
    return 0;
}

// 内接円
Circle incircle(const Point &p1, const Point &p2, const Point &p3) {
    long double d = abs((p1 - p2)) + abs(p2 - p3) + abs(p3 - p1);
    Point p = p1 + (abs(p3 - p1) / d) * (p2 - p1) + (abs(p2 - p1) / d) * (p3 - p1);
    long double r = abs(cross(p2 - p1, p3 - p1)) / d;
    return Circle(p, r);
}

// 外接円
Circle circumscribed_circle(const Point &p1, const Point &p2, const Point &p3) {
    long double a = abs(p1 - p2), b = abs(p2 - p3), c = abs(p3 - p1), S = abs(cross(p2 - p1, p3 - p1)) * 0.5;
    long double cx = norm(p2 - p1) * (p3 - p1).imag() - norm(p3 - p1) * (p2 - p1).imag(), cy = norm(p3 - p1) * (p2 - p1).real() - norm(p2 - p1) * (p3 - p1).real();
    cx /= 2.0 * cross(p2 - p1, p3 - p1);
    cy /= 2.0 * cross(p2 - p1, p3 - p1);
    Point p = p1 + Point(cx, cy);
    long double r = a * b * c / (4.0 * S);
    return Circle(p, r);
}

// 円と直線の交点
vector<Point> cross_points(Circle c, Line l) {
    Point proj = projection(l, c.p);
    long double d = abs(proj - c.p);
    if (d > c.r + EPS) {
        return {};
    } else if (abs(c.r - abs(proj - c.p)) < EPS) {
        return {proj};
    } else {
        long double s = sqrt(c.r * c.r - norm(proj - c.p));
        return {proj - (s / abs(l.b - l.a)) * (l.b - l.a), proj + (s / abs(l.b - l.a)) * (l.b - l.a)};
    }
}

// 円と円の交点
vector<Point> cross_points(Circle c1, Circle c2) {
    int t = intersection_of_circle(c1, c2);
    if (t == 0 || t == 4) {
        return {};
    }
    if (t == 3) {
        return {c1.p + (c1.r / (c1.r + c2.r)) * (c2.p - c1.p)};
    }
    if (t == 1) {
        if (c1.r > c2.r) return {(-c2.r / abs(c1.r - c2.r)) * c1.p + (c1.r / abs(c1.r - c2.r)) * c2.p};
        return {(c2.r / abs(c1.r - c2.r)) * c1.p + (-c1.r / abs(c1.r - c2.r)) * c2.p};
    }
    long double d = abs(c1.p - c2.p);
    long double s = (c1.r * c1.r - c2.r * c2.r + d * d) / (2.0 * d);
    Point p = c1.p + (s / d) * (c2.p - c1.p);
    return {p - (sqrt(c1.r * c1.r - s * s) / d) * Point((c2.p - c1.p).imag(), -(c2.p - c1.p).real()), p + (sqrt(c1.r * c1.r - s * s) / d) * Point((c2.p - c1.p).imag(), -(c2.p - c1.p).real())};
}

// 円の接線
vector<Point> tangent(Circle c, Point p) {
    return cross_points(c, Circle(p, sqrt(norm(c.p - p) - c.r * c.r)));
}

// 円の共通接線
vector<Point> common_tangent(Circle c1, Circle c2) {
    long double d = norm(c1.p - c2.p);
    long double d1 = d - (c1.r + c2.r) * (c1.r + c2.r) + c2.r * c2.r;
    vector<Point> ps;
    if (d1 > -EPS) {
        d1 = sqrt(max(d1, (long double)0.0));
        vector<Point> ps1 = cross_points(c1, Circle(c2.p, d1));
        for (auto p : ps1) ps.push_back(p);
    }
    long double d2 = d - (c1.r - c2.r) * (c1.r - c2.r) + c2.r * c2.r;
    if (d2 > -EPS) {
        d2 = sqrt(max(d2, (long double)0.0));
        vector<Point> ps2 = cross_points(c1, Circle(c2.p, d2));
        for (auto p : ps2) ps.push_back(p);
    }
    return ps;
}

// 円の共通部分の面積
long double area_of_intersection(Circle c1, Circle c2) {
    int t = intersection_of_circle(c1, c2);
    if (t >= 3) {
        return 0;
    }
    if (t <= 1) {
        return pi * min(c1.r, c2.r) * min(c1.r, c2.r);
    }
    vector<Point> ps = cross_points(c1, c2);
    long double a1 = arg(ps[0] - c1.p) - arg(ps[1] - c1.p), a2 = arg(ps[1] - c2.p) - arg(ps[0] - c2.p);
    if (a1 < -EPS) a1 += 2.0 * pi;
    if (a2 < -EPS) a2 += 2.0 * pi;
    return (a1 / 2) * c1.r * c1.r + (a2 / 2) * c2.r * c2.r - abs(area({ps[0], c1.p, ps[1], c2.p}));
}

const double INF=1e18;

int main() {
    while(1){
        int N;
        cin>>N;
        if(N==0)return 0;
        vector<int>K(3);
        rep(i,0,3){
            cin>>K[i];
            K[i]--;
        }
        Polygon ply(N);
        rep(i,0,N){
            int x,y;
            cin>>x>>y;
            ply[i]=Point(x,y);
        }
        vector<long double>L;
        L.push_back(0.0);
        vector<vector<long double>>sum(3);
        rep(t,0,3){
            long double cnt=0;
            sum[t].push_back(cnt);
            rep(i,0,N){
                cnt+=abs(ply[(K[t]+i+1)%N]-ply[(K[t]+i)%N]);
                L.push_back(cnt);
                sum[t].push_back(cnt);
            }
        }
        sort(all(L));
        int S=L.size();
        long double ans=INF;
        auto f=[&](long double lx)-> long double {
            Polygon tri;
            rep(t,0,3){
                long double l=lx;
                int ok=0,ng=N+1;
                while(ng-ok>1){
                    int mid=(ok+ng)/2;
                    if(sum[t][mid]<=l)ok=mid;
                    else ng=mid;
                }
                l-=sum[t][ok];
                long double to=abs(ply[(K[t]+ok+1)%N]-ply[(K[t]+ok)%N]);
                tri.push_back(ply[(K[t]+ok)%N]
                        +(ply[(K[t]+ok+1)%N]-ply[(K[t]+ok)%N])*l/to);
            }
            assert((int)tri.size()==3);
            return abs(area(tri));
        };
        rep(i,0,S-1){
            if(abs(L[i+1]-L[i])<EPS)continue;
            long double l=L[i],r=L[i+1];
            rep(t,0,120){
                long double nl=(2*l+r)/3.0,nr=(l+2*r)/3.0;
                if(f(nl)<f(nr))r=nr;
                else l=nl;
            }
            chmin(ans,f((l+r)/2.0));
        }
        cout<<ans<<endl;
    }
}
accuracy: 1
time_ms: 1380
memory_kb: 4224
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;

// 書きかけの幾何ライブラリ
// バグがあるかも

namespace geometry {

using Real = long double;
constexpr Real eps = 1e-12;
constexpr Real PI = acosl(-1);
constexpr Real INF_REAL = numeric_limits<Real>::max();

bool equal_eps(Real a, Real b) {
    return abs(a - b) < eps;
}

int sgn(Real a) {
    return equal_eps(a, 0) ? 0 : a > 0 ? 1 : -1;
}

struct Point {
    Real x, y;
    constexpr Point() : Point(0, 0) {}
    constexpr Point(Real _x, Real _y) : x(_x), y(_y) {}
    constexpr Point(const pair<Real, Real> &p) : x(p.first), y(p.second) {}
    Point &operator+=(const Point &p) {
        x += p.x;
        y += p.y;
        return *this;
    }
    Point &operator-=(const Point &p) {
        x -= p.x;
        y -= p.y;
        return *this;
    }
    Point &operator*=(const Real &r) {
        x *= r;
        y *= r;
        return *this;
    }
    Point &operator/=(const Real &r) {
        assert(!equal_eps(r, 0));
        x /= r;
        y /= r;
        return *this;
    }
    Point operator+(const Point &p) const { return Point(*this) += p; }
    Point operator-(const Point &p) const { return Point(*this) -= p; }
    Point operator*(const Real &r) const { return Point(*this) *= r; }
    Point operator/(const Real &r) const { return Point(*this) /= r; }
    Point operator-() const { return Point() - *this; }
    bool operator==(const Point &p) const {
        return equal_eps(x, p.x) && equal_eps(y, p.y);
    }
    bool operator!=(const Point &p) const {
        return !equal_eps(x, p.x) || !equal_eps(y, p.y);
    }
    Point rotate(Real rad) const {
        Real c = cosl(rad), s = sinl(rad);
        Real tx = x * c - y * s;
        Real ty = x * s + y * c;
        return Point(tx, ty);
    }
    Point unit() const {
        return (*this) / metric();
    }
    Real Re() const { return x; }
    Real Im() const { return y; }
    Real norm() const { return x * x + y * y; }
    Real metric() const { return sqrtl(norm()); }
    Real arg() const { return atan2l(y, x); }
    Real arg(Point q1, Point q2) const {
        q1 -= *this, q2 -= *this;
        return abs(q1.arg() - q2.arg());
    }
    friend Point operator*(Real r, const Point &p) {
        return p * r;
    }
    friend Point operator/(Real r, const Point &p) {
        return p / r;
    }
};

Real Re(const Point &p) { return p.Re(); }
Real Im(const Point &p) { return p.Im(); }
Real dot(const Point &p, const Point &q) {
    return p.x * q.x + p.y * q.y;
}
Real cross(const Point &p, const Point &q) {
    return p.x * q.y - p.y * q.x;
}
Real norm(const Point &p) {
    return p.norm();
}
Real metric(const Point &p) {
    return p.metric();
}
Real metric(const Point &p, const Point &q) {
    return metric(p - q);
}
Real arg(const Point &p) {
    return p.arg();
}

bool equal_point(const Point &p, const Point &q) {
    return equal_eps(p.x, q.x) && equal_eps(p.y, q.y);
}

constexpr Point INF_POINT = Point(INF_REAL, INF_REAL);

// a を基準にした b と c の位置関係
int ccw(const Point &a, const Point &b, const Point &c) {
    Point p = b - a, q = c - a;
    if (cross(p, q) > eps) return 1; // a, b, c の順で反時計回り
    if (cross(p, q) < -eps) return -1; // a, b, c の順で時計回り
    if (min(norm(p), norm(q)) < eps * eps) return 0; // a = c or b = c
    if (dot(p, q) < eps) return 2; // c, a, b の順で一直線
    if (norm(p) < norm(q)) return -2; // a, b, c の順で一直線
    return 0; // a, c, b の順で一直線
}

istream &operator>>(istream &is, Point& p) {
    Real x, y;
    is >> x >> y;
    p = Point(x, y);
    return is;
}

} // namespace geometry

namespace geometry {

Real area_of_triangle(Point p1, Point p2, Point p3) {
    p2 -= p1, p3 -= p1;
    return abs(p2.x * p3.y - p2.y * p3.x) / 2;
}

} // namespace geometry
using namespace geometry;

bool solve() {
    int N;
    cin >> N;
    if (N == 0) return false;
    vector<int> id(3);
    for (int &i : id) cin >> i, i--;
    vector<Point> P(2 * N);
    for (int i = 0; i < N; i++) {
        cin >> P[i];
        P[i + N] = P[i];
    }
    Real ans = INF_REAL;
    vector<Real> d(3);
    vector<Point> p(3);
    for (int i = 0; i < 3; i++) {
        d[i] = metric(P[id[i]], P[id[i] + 1]);
        p[i] = P[id[i]];
    }
    auto s = [&] (Real t) -> Real {
        vector<Point> q(3);
        for (int k = 0; k < 3; k++) {
            int i = id[k];
            q[k] = p[k] + t * (P[i + 1] - P[i]).unit();
        }
        auto res = area_of_triangle(q[0], q[1], q[2]);
        ans = min(ans, res);
        return res;
    };
    auto f = [&] (Real r) -> void {
        Real l = 0;
        for (int t = 0; t < 100; t++) {
            Real ml = (l + l + r) / 3;
            Real mr = (l + r + r) / 3;
            auto sl = s(ml), sr = s(mr);
            if (sl < sr) r = mr;
            else l = ml;
        }
    };
    for (int t = 0; t < 3 * N; t++) {
        auto r = *min_element(d.begin(), d.end());
        f(r);
        for (int i = 0; i < 3; i++) {
            d[i] -= r;
            if (equal_eps(d[i], 0)) {
                id[i]++;
                id[i] %= N;
                d[i] = metric(P[id[i]], P[id[i] + 1]);
                p[i] = P[id[i]];
            } else {
                p[i] = p[i] + r * (P[id[i] + 1] - P[id[i]]).unit();
            }
        }
    }
    cout << fixed << setprecision(16) << ans << '\n';
    return true;
}

int main() {
    while (solve()) {}
}
accuracy: 1
time_ms: 220
memory_kb: 3840
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;

// 書きかけの幾何ライブラリ
// バグがあるかも

namespace geometry {

using Real = long double;
constexpr Real eps = 1e-12;
constexpr Real PI = acosl(-1);
constexpr Real INF_REAL = numeric_limits<Real>::max();

bool equal_eps(Real a, Real b) {
    return abs(a - b) < eps;
}

int sgn(Real a) {
    return equal_eps(a, 0) ? 0 : a > 0 ? 1 : -1;
}

struct Point {
    Real x, y;
    constexpr Point() : Point(0, 0) {}
    constexpr Point(Real _x, Real _y) : x(_x), y(_y) {}
    constexpr Point(const pair<Real, Real> &p) : x(p.first), y(p.second) {}
    Point &operator+=(const Point &p) {
        x += p.x;
        y += p.y;
        return *this;
    }
    Point &operator-=(const Point &p) {
        x -= p.x;
        y -= p.y;
        return *this;
    }
    Point &operator*=(const Real &r) {
        x *= r;
        y *= r;
        return *this;
    }
    Point &operator/=(const Real &r) {
        assert(!equal_eps(r, 0));
        x /= r;
        y /= r;
        return *this;
    }
    Point operator+(const Point &p) const { return Point(*this) += p; }
    Point operator-(const Point &p) const { return Point(*this) -= p; }
    Point operator*(const Real &r) const { return Point(*this) *= r; }
    Point operator/(const Real &r) const { return Point(*this) /= r; }
    Point operator-() const { return Point() - *this; }
    bool operator==(const Point &p) const {
        return equal_eps(x, p.x) && equal_eps(y, p.y);
    }
    bool operator!=(const Point &p) const {
        return !equal_eps(x, p.x) || !equal_eps(y, p.y);
    }
    Point rotate(Real rad) const {
        Real c = cosl(rad), s = sinl(rad);
        Real tx = x * c - y * s;
        Real ty = x * s + y * c;
        return Point(tx, ty);
    }
    Point unit() const {
        return (*this) / metric();
    }
    Real Re() const { return x; }
    Real Im() const { return y; }
    Real norm() const { return x * x + y * y; }
    Real metric() const { return sqrtl(norm()); }
    Real arg() const { return atan2l(y, x); }
    Real arg(Point q1, Point q2) const {
        q1 -= *this, q2 -= *this;
        return abs(q1.arg() - q2.arg());
    }
    friend Point operator*(Real r, const Point &p) {
        return p * r;
    }
    friend Point operator/(Real r, const Point &p) {
        return p / r;
    }
};

Real Re(const Point &p) { return p.Re(); }
Real Im(const Point &p) { return p.Im(); }
Real dot(const Point &p, const Point &q) {
    return p.x * q.x + p.y * q.y;
}
Real cross(const Point &p, const Point &q) {
    return p.x * q.y - p.y * q.x;
}
Real norm(const Point &p) {
    return p.norm();
}
Real metric(const Point &p) {
    return p.metric();
}
Real metric(const Point &p, const Point &q) {
    return metric(p - q);
}
Real arg(const Point &p) {
    return p.arg();
}

bool equal_point(const Point &p, const Point &q) {
    return equal_eps(p.x, q.x) && equal_eps(p.y, q.y);
}

constexpr Point INF_POINT = Point(INF_REAL, INF_REAL);

// a を基準にした b と c の位置関係
int ccw(const Point &a, const Point &b, const Point &c) {
    Point p = b - a, q = c - a;
    if (cross(p, q) > eps) return 1; // a, b, c の順で反時計回り
    if (cross(p, q) < -eps) return -1; // a, b, c の順で時計回り
    if (min(norm(p), norm(q)) < eps * eps) return 0; // a = c or b = c
    if (dot(p, q) < eps) return 2; // c, a, b の順で一直線
    if (norm(p) < norm(q)) return -2; // a, b, c の順で一直線
    return 0; // a, c, b の順で一直線
}

istream &operator>>(istream &is, Point& p) {
    Real x, y;
    is >> x >> y;
    p = Point(x, y);
    return is;
}

} // namespace geometry

namespace geometry {

Real area_of_triangle(Point p1, Point p2, Point p3) {
    p2 -= p1, p3 -= p1;
    return abs(p2.x * p3.y - p2.y * p3.x) / 2;
}

} // namespace geometry
using namespace geometry;

bool solve() {
    int N;
    cin >> N;
    if (N == 0) return false;
    vector<int> id(3);
    for (int &i : id) cin >> i, i--;
    vector<Point> P(2 * N);
    for (int i = 0; i < N; i++) {
        cin >> P[i];
        P[i + N] = P[i];
    }
    Real ans = INF_REAL;
    vector<Real> d(3);
    vector<Point> p(3);
    for (int i = 0; i < 3; i++) {
        d[i] = metric(P[id[i]], P[id[i] + 1]);
        p[i] = P[id[i]];
    }
    auto s = [&] (Real t) -> Real {
        vector<Point> q(3);
        for (int k = 0; k < 3; k++) {
            int i = id[k];
            q[k] = p[k] + t * (P[i + 1] - P[i]).unit();
        }
        auto res = area_of_triangle(q[0], q[1], q[2]);
        ans = min(ans, res);
        return res;
    };
    auto f = [&] (Real r) -> void {
        Real l = 0;
        for (int t = 0; t < 100; t++) {
            Real ml = (l + l + r) / 3;
            Real mr = (l + r + r) / 3;
            auto sl = s(ml), sr = s(mr);
            if (sl < sr) r = mr;
            else l = ml;
        }
    };
    for (int t = 0; t <= 3 * N; t++) {
        auto r = *min_element(d.begin(), d.end());
        f(r);
        for (int k = 0; k < 3; k++) {
            int &i = id[k];
            d[k] -= r;
            if (equal_eps(d[k], 0)) {
                i = (i + 1) % N;
                p[k] = P[i];
                d[k] = metric(P[i], P[i + 1]);
            } else {
                p[k] = p[k] + r * (P[i + 1] - P[i]).unit();
            }
        }
    }
    cout << fixed << setprecision(16) << ans << '\n';
    return true;
}

int main() {
    while (solve()) {}
}
accuracy: 1
time_ms: 220
memory_kb: 3968
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;

#define rep2(i, m, n) for (int i = (m); i < (n); ++i)
#define rep(i, n) rep2(i, 0, n)
#define all(...) std::begin(__VA_ARGS__), std::end(__VA_ARGS__)
#define INF 1001001001001001001ll
#define inf (int)1001001000

ll gcd(ll x, ll y) {	if (x == 0) return y;	return gcd(y%x, x);} 
ll lcm(ll x, ll y) { __int128_t xx,yy; xx=x; yy=y; __int128_t ans=xx * yy / gcd(x, y); ll ans2=ans; return ans2; }
template<typename T>
T POW(T x, ll n){T ret=1;	while(n>0){		if(n&1) ret=ret*x;		x=x*x;		n>>=1;	}	return ret;}
template<typename T>
T modpow(T a, ll n, T p) {	if(n==0) return (T)1;  if (n == 1) return a % p;  if (n % 2 == 1) return (a * modpow(a, n - 1, p)) % p;  T t = modpow(a, n / 2, p);  return (t * t) % p;}
template<typename T>
T modinv(T a, T m) {	if(m==0)return (T)1;	T b = m, u = 1, v = 0;	while (b) {		T t = a / b;		a -= t * b; swap(a, b);		u -= t * v; swap(u, v);	}	u %= m;	if (u < 0) u += m;	return u;}
/*
const int MAXCOMB=510000;
std::vector<mint> fac(MAXCOMB), finv(MAXCOMB), inv(MAXCOMB);
void COMinit() {fac[0] = fac[1] = 1;finv[0] = finv[1] = 1;inv[1] = 1;for (int i = 2; i < MAXCOMB; i++) {fac[i] = fac[i - 1] * i;inv[i] = mint(0) - inv[mint::mod() % i] * (mint::mod() / i);finv[i] = finv[i - 1] * inv[i];}}
mint COM(int n, int k) {if (n < k) return 0;if (n < 0 || k < 0) return 0;return fac[n] * finv[k] * finv[n - k];}
*/
template <typename T> inline bool chmax(T &a, T b) { return ((a < b) ? (a = b, true) : (false));}
template <typename T> inline bool chmin(T &a, T b) { return ((a > b) ? (a = b, true) : (false));}

int SOLVEFIN = 0;

struct Line{
    double x1,y1;
    double x2,y2;
    int ind;
    double length;
};

vector<Line> line;
vector<double> lengthsum;
vector<int> pos(3);
int n;

pair<double,double> cor(int v, double time){ //time時間経った時の頂点vの座標を得る
    int l = -1;//最初からl本は全て通っている
    int r = n+1;
    while(r-l>1){
        int mid = (l+r)/2;
        double now = lengthsum[pos[v]+mid]-lengthsum[pos[v]];
        if(now<=time)l=mid;
        else r=mid;
    }
    double rem = time - lengthsum[pos[v]+l] + lengthsum[pos[v]];
    int ind = (pos[v]+l)%n;
    double x = line[ind].x1 + (line[ind].x2-line[ind].x1)*rem/line[ind].length;
    double y = line[ind].y1 + (line[ind].y2-line[ind].y1)*rem/line[ind].length;
    return make_pair(x,y);

}

double area(double x1, double y1, double x2, double y2, double x3, double y3){
    //cout<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<" "<<x3<<" "<<y3<<endl;
    return (abs((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1))/2);
    
}

void solve(){
    cin>>n;
    rep(i,3){cin>>pos[i];pos[i]--;}
    
    if(n==0){
        SOLVEFIN=1;
        return;
    }
    vector<pair<double,double>> pt;
    line.resize(n);
    lengthsum.resize(2*n+3);//無/0/0+1/0+1+2/...
    rep(i,n){
        double x; double y;
        cin>>x>>y;
        pt.push_back({x,y});
    }
    rep(i,n){
        double x1 =pt[i].first;
        double y1 = pt[i].second;
        double x2 = pt[(i+1)%n].first;
        double y2 = pt[(i+1)%n].second;
        double length = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
        line[i] = {x1,y1,x2,y2,i,length};
    }
    rep(i,2*n+2){
        lengthsum[i+1]=lengthsum[i]+line[i%n].length;
    }
    vector<double> etime;
    etime.push_back(0);
    rep(i,3){
        double now = 0;
        rep(j,n){
            now+=line[(pos[i]+j)%n].length;
            etime.push_back(now);
        }
    }

    double ans = area(pt[pos[0]].first,pt[pos[0]].second,
    pt[pos[1]].first,pt[pos[1]].second,pt[pos[2]].first,pt[pos[2]].second);
    sort(all(etime));
    int sz = etime.size();
    rep(i,sz-1){
        //cout<<ans<<" "<<etime[i]<<endl;
        double lt = etime[i];
        double rt = etime[i+1];
            auto res01 = cor(0,lt);
            auto res02 = cor(1,lt);
            auto res03 = cor(2,lt);
            double nowarea = area(res01.first,res01.second,res02.first,res02.second,
            res03.first,res03.second);
            //cout<<res01.first<<" "<<res01.second<<endl;
        while(rt-lt>=1e-9){
            //cout<<nowarea<<endl;
            double lt1 = (lt*2+rt)/3;
            double lt2 = (lt+rt*2)/3;
            auto res1 = cor(0,lt1);
            auto res2 = cor(1,lt1);
            auto res3 = cor(2,lt1);
            double area1 = area(res1.first,res1.second,res2.first,res2.second,
            res3.first,res3.second);
             res1 = cor(0,lt2);
             res2 = cor(1,lt2);
             res3 = cor(2,lt2);
            double area2 = area(res1.first,res1.second,res2.first,res2.second,
            res3.first,res3.second);
            if(area1>area2){
                lt=lt1;
                nowarea = area2;
            }
            else {rt=lt2;nowarea=area1;}
        }
        chmin(ans,nowarea);
    }
    cout<<ans<<endl;

}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);
	while(SOLVEFIN == 0) solve();
}
accuracy: 1
time_ms: 270
memory_kb: 3728
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(a) a.begin(),a.end()
#define reps(i, a, n) for (int i = (a); i < (int)(n); i++)
#define rep(i, n) reps(i, 0, n)
#define rreps(i, a, n) for (int i = (a); i > (int)(n); i--)
const long long mod = 1000000007;
const long long INF = 1e18;
ll myceil(ll a, ll b) {return (a+b-1)/b;}


double ans = INF;
int n,kp,kq,kr;
double np = 0, nq = 0, nr = 0;

vector<double> x(0),y(0);
vector<pair<double,double>> mov(0);


double g(double nw) {
    double px = x[kp]+(np+nw)*mov[kp].first;
    double py = y[kp]+(np+nw)*mov[kp].second;
    double qx = x[kq]+(nq+nw)*mov[kq].first;
    double qy = y[kq]+(nq+nw)*mov[kq].second;
    double rx = x[kr]+(nr+nw)*mov[kr].first;
    double ry = y[kr]+(nr+nw)*mov[kr].second;

    return abs((qx-px)*(ry-py)-(rx-px)*(qy-py))/2;
}


void f(double tm) {
    double ok = 0;
    double ng = tm;
    rep(i,100) {
        double l = (ok*2+ng)/3;
        double r = (ok+2*ng)/3;

        if (g(l)>g(r)) {
            ok = l;
        }
        else {
            ng = r;
        }
    }
    ans = min(ans,g((ok+ng)/2));
}


void solve() {
    kp--; kq--; kr--;
    x.resize(n);
    y.resize(n);
    rep(i,n) {
        cin >> x[i] >> y[i];
    }

    vector<double> dis(n);

    rep(i,n) {
        dis[i] = pow((x[(i+1)%n]-x[i])*(x[(i+1)%n]-x[i]) + (y[(i+1)%n]-y[i])*(y[(i+1)%n]-y[i]),0.5);
    }

    mov.resize(n);
    rep(i,n) {
        mov[i].first = (x[(i+1)%n]-x[i])/dis[i];
        mov[i].second = (y[(i+1)%n]-y[i])/dis[i];
    }

    np = 0;
    nq = 0;
    nr = 0;
    ans = INF;
    
    rep(i,3*n) {
        if (dis[kp]-np > dis[kq]-nq) {
            if (dis[kq]-nq > dis[kr]-nr) {
                f(dis[kr]-nr);
                np += dis[kr]-nr;
                nq += dis[kr]-nr;
                nr = 0;
                kr = (kr+1)%n;
            }
            else {
                f(dis[kq]-nq);
                np += dis[kq]-nq;
                nr += dis[kq]-nq;
                nq = 0;
                kq = (kq+1)%n;
            }
        }
        else {
            if (dis[kp]-np > dis[kr]-nr) {
                f(dis[kr]-nr);
                np += dis[kr]-nr;
                nq += dis[kr]-nr;
                nr = 0;
                kr = (kr+1)%n;
            }
            else {
                f(dis[kp]-np);
                nq += dis[kp]-np;
                nr += dis[kp]-np;
                np = 0;
                kp = (kp+1)%n;
            }
        }
    }

    cout << ans << endl;
    return;
}


int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << setprecision(10) << fixed;
    int _ = 1;

    // cin >> _;

    while (cin >> n >> kp >> kq >> kr && n != 0) {
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3904
final_rank: 15

code_snippet: // (⁠◕⁠ᴗ⁠◕⁠✿⁠)

#include <bits/stdc++.h>
// #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define srep(i, s, n) for (ll i = s; i < (n); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
template<typename T> using vc = vector<T>;
template<typename T> using vv = vc<vc<T>>;
template<typename T> using vvv = vv<vc<T>>;
using vi = vc<int>;using vvi = vv<int>; using vvvi = vv<vi>;
using ll = long long;using vl = vc<ll>;using vvl = vv<ll>; using vvvl = vv<vl>;
using ld = long double; using vld = vc<ld>; using vvld = vc<vld>; using vvvld = vc<vvld>;
using uint = unsigned int;
using ull = unsigned long long;
const ld pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
// const ll mod = 1000000007;
const ll mod = 998244353;
inline bool inside(ll y, ll x, ll H, ll W) {return 0 <= (y) and (y) < (H) and 0 <= (x) and (x) < (W); }

#define debug(var)  do{std::cout << #var << " : \n";view(var);}while(0)
template<typename T> void view(T e){cout << e << endl;}
template<typename T> void view(const vc<T>& v){for(const auto& e : v){ cout << e << " "; } cout << endl;}
template<typename T> void view(const vv<T>& vv){ for(const auto& v : vv){ view(v); } }

double d(double x1, double y1, double x2, double y2){return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));}

void solve(int N, vc<int> P){
    vc<double> X(3 * N), Y(3 * N); rep(i, N) cin >> X[i] >> Y[i];
    rep(i, N){
        X[i + N] = X[i];
        Y[i + N] = Y[i];
        X[i + 2 * N] = X[i];
        Y[i + 2 * N] = Y[i];
    }

    vc<double> cmsm(1, 0); rep(i, 3 * N - 1) cmsm.push_back(cmsm.back() + d(X[i], Y[i], X[i + 1], Y[i + 1]));

    double x[3], y[3];
    auto S = [&](double w){
        rep(i, 3){
            auto it = lower_bound(all(cmsm), cmsm[P[i]] + w) - cmsm.begin();
            double a = (cmsm[P[i]] + w - cmsm[it - 1]) / (cmsm[it] - cmsm[it - 1]);
            x[i] = X[it] * a + X[it - 1] * (1 - a);
            y[i] = Y[it] * a + Y[it - 1] * (1 - a);
        }
        
        x[2] -= x[0];
        y[2] -= y[0];
        x[1] -= x[0];
        y[1] -= y[0];
        double ret = abs(x[1] * y[2] - x[2] * y[1]) / (double)2;
        return ret;
    };

    vc<double> event;
    rep(i, 3) for (int j = P[i]; j <= P[i] + N; j++) event.push_back(cmsm[j] - cmsm[P[i]]);
    sort(all(event));
    
    double ans = INF;
    rep(id, len(event) - 1){
        double bottom = event[id], top = event[id + 1];
        if (top == bottom) continue;
        rep(_, 100){
            double l = (top + bottom * 2) / (double)3;
            double r = (top * 2 + bottom) / (double)3;
            double sl = S(l), sr = S(r);
            if (sl > sr) bottom = l;
            else top = r;
        }
        ans = min(ans, S(top));
    }
    cout << fixed << setprecision(16) << ans << endl;
}
int main(){
    while(true){
        int N; cin >> N;
        vi P(3); rep(i, 3) cin >> P[i];
        rep(i, 3) P[i]--;
        if (N == 0) break;
        solve(N, P);
    }
}
accuracy: 1
time_ms: 140
memory_kb: 3596
final_rank: 2

code_snippet: #include <bits/stdc++.h>
    using namespace std;
    
    template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
    template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
    #define rep(i,n) for (int i = 0; i < (n); ++i)

    typedef long long ll;
    typedef unsigned long long ull;
    using P=pair<ll,ll>;
    using tp=tuple<ll,ll,ll>;
    const int INF=1001001001;
    const ll INFL=1e18;
    const int mod=998244353;

    	#define EPS (1e-10)
		#define equals(a,b)(fabs((a)-(b))<EPS)
	
		class Point{
			public:
			double x,y;
	
			Point(double x=0,double y=0):x(x),y(y){}
	
			Point operator + (Point p){return Point(x+p.x,y+p.y);}
			Point operator - (Point p){return Point(x-p.x,y-p.y);}
			Point operator * (double a){return Point(a*x,a*y);}
			Point operator / (double a){return Point(x/a,y/a);}
	
			double abs(){return sqrt(norm());}
			double norm(){return x*x+y*y;}
	
			bool operator < (const Point &p) const{
				return x!=p.x ? x < p.x: y < p.y;
			}
			bool operator == (const Point &p) const{
				return fabs(x-p.x) < EPS && fabs(y-p.y) <EPS;
			}
		};
		typedef Point Vector;
		struct Segment{
			Point p1,p2;
			Segment(Point p1,Point p2):p1(p1),p2(p2){}
		};
		typedef Segment Line;
		class Circle{
		public:
			Point c;
			double r;
			Circle(Point c=Point(),double r=0.0):c(c),r(r){}
		};
		typedef vector<Point>Polygon;
		
		double dot(Vector a,Vector b){
			return a.x*b.x+a.y*b.y;
		}
		double cross(Vector a,Vector b){
			return a.x*b.y-a.y*b.x;
		}
		Point rot90(const Point& p){return Point(-p.y,p.x);}
		Point getCrossPoint(Line s1,Line s2){//２線分の交点
			Vector base=s2.p2-s2.p1;
			double d1=abs(cross(base,s1.p1-s2.p1));
			double d2=abs(cross(base,s1.p2-s2.p1));
			double t=d1/(d1+d2);
			return s1.p1+(s1.p2-s1.p1)*t;
		}
		Point intersection(Line s1,Line s2){//２直線の交点 http://www.deqnotes.net/acmicpc/2d_geometry/lines
			Vector a=s1.p2-s1.p1,b=s2.p2-s2.p1;
			return s1.p1+a*cross(b,s2.p1-s1.p1)/cross(b,a);
		}
		Point circumcenter(Point a,Point b,Point c){
			Line ab((a+b)/2,(a+b)/2+rot90(a-b));
			Line bc((b+c)/2,(b+c)/2+rot90(b-c));
			return getCrossPoint(ab,bc);
		}
		int ccw(Point p0,Point p1,Point p2){
			Vector a=p1-p0;
			Vector b=p2-p0;
			if(cross(a,b)>EPS){return 1;}
			if(cross(a,b)<-EPS){return -1;}
			if(dot(a,b)<-EPS){return 2;}
			if(a.norm()<b.norm()){return -2;}
			return 0;
		}
		double getarea(vector<Point>p){ //https://imagingsolution.net/math/calc_n_point_area/
			int n=p.size();
			double s=0;
			rep(i,n){
				s+=cross(p[i],p[(i+1)%n]);
			}
			s=abs(s);
			s/=2;
			return s;
		}
		vector<Point> ConvexCut(vector<Point>& s,Segment t){
			vector<Point>ans;
			int n=s.size();
			rep(j,n){
				Point p=s[j],q=s[(j+1)%n];
				double p_c=cross(t.p2-t.p1,p-t.p1);
				double q_c=cross(t.p2-t.p1,q-t.p1);
				Segment now=Segment(p,q);
	
				if(p_c+EPS>0){
					ans.push_back(p);
				}
				if(ccw(t.p1,t.p2,now.p1)*ccw(t.p1,t.p2,now.p2)==-1){
					auto e=intersection(t,now);
					ans.push_back(e);
				}
			}
			return ans;
		}

		Vector t_move(Point from,Point to,double t){
			Vector vec=to-from;
			double len=vec.abs();
			auto n_vec=(from*(len-t)+to*t)/len;
			return n_vec;
		}

    bool solve(){
		int n;
		vector<int>s(3);
		cin>>n>>s[0]>>s[1]>>s[2];
		if(!n&&!s[0]&&!s[1]&&!s[2])return false;
		s[0]--;s[1]--;s[2]--;
		vector<Point>v(n);
		rep(i,n){cin>>v[i].x>>v[i].y;}
		vector<Point>p(3);
		rep(i,3){p[i]=v[s[i]];}

		double cur_t=0,ans=INF;
		rep(z,n*3){
			double mn_t=INF;
			rep(i,3){
				Vector vec=v[(s[i]+1)%n]-p[i];
				double tmp=vec.abs();
				chmin(mn_t,tmp);
			}
			double l=0,r=mn_t;
			rep(e,100){
				double c1=(2*l+r)/3;
				double c2=(l+2*r)/3;
				
				vector<Vector>V1(3);
				rep(i,3){
					V1[i]=t_move(p[i],v[(s[i]+1)%n],c1);
				}
				double area_c1=getarea(V1);
			
				vector<Vector>V2(3);
				rep(i,3){
					V2[i]=t_move(p[i],v[(s[i]+1)%n],c2);
				}
				double area_c2=getarea(V2);
				chmin(ans,min(area_c2,area_c1));
				
				if(area_c1>area_c2){
					l=c1;
				}else {
					r=c2;
				}
			}

			rep(i,3){
				p[i]=t_move(p[i],v[(s[i]+1)%n],mn_t);
				if(p[i]==v[(s[i]+1)%n]){
					s[i]=(s[i]+1)%n;
				}
			}
		}

		printf("%.10f\n",ans);
		return true;
    }

    int main(){
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);

		while(1){
			if(!solve())return false;
		}
		
        return 0;
    }
accuracy: 1
time_ms: 160
memory_kb: 3712
final_rank: 8

code_snippet: #include <bits/stdc++.h>
    using namespace std;
    
    template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
    template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
    #define rep(i,n) for (int i = 0; i < (n); ++i)

    typedef long long ll;
    typedef unsigned long long ull;
    using P=pair<ll,ll>;
    using tp=tuple<ll,ll,ll>;
    const int INF=1001001001;
    const ll INFL=1e18;
    const int mod=998244353;

    	#define EPS (1e-10)
		#define equals(a,b)(fabs((a)-(b))<EPS)
	
		class Point{
			public:
			double x,y;
	
			Point(double x=0,double y=0):x(x),y(y){}
	
			Point operator + (Point p){return Point(x+p.x,y+p.y);}
			Point operator - (Point p){return Point(x-p.x,y-p.y);}
			Point operator * (double a){return Point(a*x,a*y);}
			Point operator / (double a){return Point(x/a,y/a);}
	
			double abs(){return sqrt(norm());}
			double norm(){return x*x+y*y;}
	
			bool operator < (const Point &p) const{
				return x!=p.x ? x < p.x: y < p.y;
			}
			bool operator == (const Point &p) const{
				return fabs(x-p.x) < EPS && fabs(y-p.y) <EPS;
			}
		};
		typedef Point Vector;
		struct Segment{
			Point p1,p2;
			Segment(Point p1,Point p2):p1(p1),p2(p2){}
		};
		typedef Segment Line;
		class Circle{
		public:
			Point c;
			double r;
			Circle(Point c=Point(),double r=0.0):c(c),r(r){}
		};
		typedef vector<Point>Polygon;
		
		double dot(Vector a,Vector b){
			return a.x*b.x+a.y*b.y;
		}
		double cross(Vector a,Vector b){
			return a.x*b.y-a.y*b.x;
		}
		Point rot90(const Point& p){return Point(-p.y,p.x);}
		Point getCrossPoint(Line s1,Line s2){//２線分の交点
			Vector base=s2.p2-s2.p1;
			double d1=abs(cross(base,s1.p1-s2.p1));
			double d2=abs(cross(base,s1.p2-s2.p1));
			double t=d1/(d1+d2);
			return s1.p1+(s1.p2-s1.p1)*t;
		}
		Point intersection(Line s1,Line s2){//２直線の交点 http://www.deqnotes.net/acmicpc/2d_geometry/lines
			Vector a=s1.p2-s1.p1,b=s2.p2-s2.p1;
			return s1.p1+a*cross(b,s2.p1-s1.p1)/cross(b,a);
		}
		Point circumcenter(Point a,Point b,Point c){
			Line ab((a+b)/2,(a+b)/2+rot90(a-b));
			Line bc((b+c)/2,(b+c)/2+rot90(b-c));
			return getCrossPoint(ab,bc);
		}
		int ccw(Point p0,Point p1,Point p2){
			Vector a=p1-p0;
			Vector b=p2-p0;
			if(cross(a,b)>EPS){return 1;}
			if(cross(a,b)<-EPS){return -1;}
			if(dot(a,b)<-EPS){return 2;}
			if(a.norm()<b.norm()){return -2;}
			return 0;
		}
		double getarea(vector<Point>p){ //https://imagingsolution.net/math/calc_n_point_area/
			int n=p.size();
			double s=0;
			rep(i,n){
				s+=cross(p[i],p[(i+1)%n]);
			}
			s=abs(s);
			s/=2;
			return s;
		}
		vector<Point> ConvexCut(vector<Point>& s,Segment t){
			vector<Point>ans;
			int n=s.size();
			rep(j,n){
				Point p=s[j],q=s[(j+1)%n];
				double p_c=cross(t.p2-t.p1,p-t.p1);
				double q_c=cross(t.p2-t.p1,q-t.p1);
				Segment now=Segment(p,q);
	
				if(p_c+EPS>0){
					ans.push_back(p);
				}
				if(ccw(t.p1,t.p2,now.p1)*ccw(t.p1,t.p2,now.p2)==-1){
					auto e=intersection(t,now);
					ans.push_back(e);
				}
			}
			return ans;
		}

		Vector t_move(Point from,Point to,double t){
			Vector vec=to-from;
			double len=vec.abs();
			auto n_vec=(from*(len-t)+to*t)/len;
			return n_vec;
		}

    bool solve(){
		int n;
		vector<int>s(3);
		cin>>n>>s[0]>>s[1]>>s[2];
		if(!n&&!s[0]&&!s[1]&&!s[2])return false;
		s[0]--;s[1]--;s[2]--;
		vector<Point>v(n);
		rep(i,n){cin>>v[i].x>>v[i].y;}
		vector<Point>p(3);
		rep(i,3){p[i]=v[s[i]];}

		double cur_t=0,ans=INF;
		rep(z,n*100){
			double mn_t=INF;
			rep(i,3){
				Vector vec=v[(s[i]+1)%n]-p[i];
				double tmp=vec.abs();
				chmin(mn_t,tmp);
			}
			double l=0,r=mn_t;
			rep(e,100){
				double c1=(2*l+r)/3;
				double c2=(l+2*r)/3;
				
				vector<Vector>V1(3);
				rep(i,3){
					V1[i]=t_move(p[i],v[(s[i]+1)%n],c1);
				}
				double area_c1=getarea(V1);
			
				vector<Vector>V2(3);
				rep(i,3){
					V2[i]=t_move(p[i],v[(s[i]+1)%n],c2);
				}
				double area_c2=getarea(V2);
				chmin(ans,min(area_c2,area_c1));
				
				if(area_c1>area_c2){
					l=c1;
				}else {
					r=c2;
				}
			}

			rep(i,3){
				p[i]=t_move(p[i],v[(s[i]+1)%n],mn_t);
				if(p[i]==v[(s[i]+1)%n]){
					s[i]=(s[i]+1)%n;
				}
			}
		}

		printf("%.10f\n",ans);
		return true;
    }

    int main(){
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);

		while(1){
			if(!solve())return false;
		}
		
        return 0;
    }
accuracy: 1
time_ms: 5320
memory_kb: 3712
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<vvb> vvvb;
typedef vector<vvvb> vvvvb;
typedef pair<ll,ll> pi;
typedef pair<ll,pi> ppi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define RFOR(i,l,r) for(ll i=r-1;i>=l;i--)
#define RREP(i,n) RFOR(i,0,n)
#define sz(A) (ll)(A.size())
#define ALL(A) A.begin(),A.end()
#define LB(A,x) (ll)(lower_bound(ALL(A),x)-A.begin())
#define UB(A,x) (ll)(upper_bound(ALL(A),x)-A.begin())
#define COU(A,x) (UB(A,x)-LB(A,x))
#define F first
#define S second
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.F<<" "<<p.S;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.F>>p.S;return is;}
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){REP(i,sz(v))os<<v[i]<<(i+1!=sz(v)?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<class T>bool chmax(T&a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T>bool chmin(T&a,T b){if(b<a){a=b;return 1;}return 0;}
const ll mod=998244353;
template<const long long int mod=998244353>
struct modint{
  using mint=modint<mod>;
  long long int x;
  modint(long long int _x=0):x(_x%mod){if(x<0)x+=mod;}
  long long int val(){return x;}
  mint&operator=(const mint&a){x=a.x;return *this;}
  mint&operator+=(const mint&a){x+=a.x;if(x>=mod)x-=mod;return *this;}
  mint&operator-=(const mint&a){x-=a.x;if(x<0)x+=mod;return *this;}
  mint&operator*=(const mint&a){x*=a.x;x%=mod;return *this;}
  friend mint operator+(const mint&a,const mint&b){return mint(a)+=b;}
  friend mint operator-(const mint&a,const mint&b){return mint(a)-=b;}
  friend mint operator*(const mint&a,const mint&b){return mint(a)*=b;}
  mint operator-()const{return mint(0)-*this;}
  mint pow(long long int n){
    if(!n)return 1;
    mint a=1;
    mint _x=x;
    while(n){
      if(n&1)a*=_x;
      _x=_x*_x;n>>=1;
    }
    return a;
  }
  mint inv(){return pow(mod-2);}
  mint&operator/=(mint&a){return *this*=a.inv();}
  friend mint operator/(const mint&a,mint b){return mint(a)/=b;}
};
using mint=modint<998244353>;
struct point{
    ld x,y;
    point operator+(point p){
        return point{x+p.x,y+p.y};
    }
    point operator-(point p){
        return point{x-p.x,y-p.y};
    }
    point operator*(ld k){
        return point{k*x,k*y};
    }
};
#define EPS 1e-10
int main(){
    while(1){
        ll N,P,Q,R;cin>>N>>P>>Q>>R;P--;Q--;R--;
        if(!N)return 0;
        vector<pi>A(N);cin>>A;
        auto d=[](pi a,pi b){
            return sqrt((a.F-b.F)*(a.F-b.F)+(a.S-b.S)*(a.S-b.S));
        };
        auto S=[](point a,point b,point c){
            b=b-a;c=c-a;
            return (b.x*c.y-b.y*c.x)/2;
        };
        auto f=[&](point p1,point p2,point q1,point q2,point r1,point r2){
            ld ans=min(abs(S(p1,q1,r1)),abs(S(p2,q2,r2)));
            {
                ld l=0,r=1;
                while(r-l>1e-8){
                    ld m1=(2*l+r)/3,m2=(l+2*r)/3;
                    ld s0=S(p1+(p2-p1)*l,q1+(q2-q1)*l,r1+(r2-r1)*l);
                    ld s1=S(p1+(p2-p1)*m1,q1+(q2-q1)*m1,r1+(r2-r1)*m1);
                    ld s2=S(p1+(p2-p1)*m2,q1+(q2-q1)*m2,r1+(r2-r1)*m2);
                    ld s3=S(p1+(p2-p1)*r,q1+(q2-q1)*r,r1+(r2-r1)*r);
                    if(s1<s2)r=m2;
                    else l=m1;
                }
                ld m=(l+r)/2;
                chmin(ans,abs(S(p1+(p2-p1)*m,q1+(q2-q1)*m,r1+(r2-r1)*m)));
                ld a=S(p1,q1,r1),b=S(p2,q2,r2),c=S(p1+(p2-p1)*m,q1+(q2-q1)*m,r1+(r2-r1)*m);
                if(a*c<0||b*c<0)ans=0;
            }
            {
                ld l=0,r=1;
                while(r-l>1e-8){
                    ld m1=(2*l+r)/3,m2=(l+2*r)/3;
                    ld s0=S(p1+(p2-p1)*l,q1+(q2-q1)*l,r1+(r2-r1)*l);
                    ld s1=S(p1+(p2-p1)*m1,q1+(q2-q1)*m1,r1+(r2-r1)*m1);
                    ld s2=S(p1+(p2-p1)*m2,q1+(q2-q1)*m2,r1+(r2-r1)*m2);
                    ld s3=S(p1+(p2-p1)*r,q1+(q2-q1)*r,r1+(r2-r1)*r);
                    if(s1>s2)r=m2;
                    else l=m1;
                }
                ld m=(l+r)/2;
                chmin(ans,abs(S(p1+(p2-p1)*m,q1+(q2-q1)*m,r1+(r2-r1)*m)));
                ld a=S(p1,q1,r1),b=S(p2,q2,r2),c=S(p1+(p2-p1)*m,q1+(q2-q1)*m,r1+(r2-r1)*m);
                if(a*c<0||b*c<0)ans=0;
            }
            return ans;
        };
        REP(i,N)A.emplace_back(A[i]);
        REP(i,N)A.emplace_back(A[i]);
        vector<ld>T;
        ld s=0,t=0,u=0;
        REP(i,N+2){
            T.emplace_back(s);s+=d(A[P+i+1],A[P+i]);
            T.emplace_back(t);t+=d(A[Q+i+1],A[Q+i]);
            T.emplace_back(u);u+=d(A[R+i+1],A[R+i]);
        }
        T.emplace_back(s);
        sort(ALL(T));
        T.erase(unique(ALL(T)),T.end());
        ld ans=1e18;
        ld p=0,q=0,r=0;
        REP(i,sz(T)-1){
            ld x=T[i+1]-T[i];
            ld a=d(A[P],A[P+1]),b=d(A[Q],A[Q+1]),c=d(A[R],A[R+1]);
            point p1=point{(ld)A[P].F,(ld)A[P].S},p2=point{(ld)A[P+1].F,(ld)A[P+1].S};
            point q1=point{(ld)A[Q].F,(ld)A[Q].S},q2=point{(ld)A[Q+1].F,(ld)A[Q+1].S};
            point r1=point{(ld)A[R].F,(ld)A[R].S},r2=point{(ld)A[R+1].F,(ld)A[R+1].S};
            auto _p1=p1+(p2-p1)*(p/a),_p2=p1+(p2-p1)*((p+x)/a);
            auto _q1=q1+(q2-q1)*(q/b),_q2=q1+(q2-q1)*((q+x)/b);
            auto _r1=r1+(r2-r1)*(r/c),_r2=r1+(r2-r1)*((r+x)/c);
            chmin(ans,f(_p1,_p2,_q1,_q2,_r1,_r2));
            p+=x,q+=x,r+=x;
            if(abs(p-a)<EPS){p=0;P++;}
            if(abs(q-b)<EPS){q=0;Q++;}
            if(abs(r-c)<EPS){r=0;R++;}
        }
        printf("%.20Lf\n",ans);
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3700
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define ALL(v) v.begin(),v.end()
#define dbg(x) cerr << #x << ": " << x << endl;
template<class F, class S>
ostream& operator << (ostream& os, pair<F,S> p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template<class Iter>
void print(Iter beg, Iter end) {
    for (Iter itr = beg; itr != end; ++itr) {
        cerr << *itr << ' ';
    }
    cerr << endl;
}
// 型
using ld = long double;
using Point = complex<ld>;
using Vec = complex<ld>;
using Seg = pair<Point, Point>;
using Line = Seg;
using Circle = pair<Point, ld>;
using Polygon = vector<Point>;
#define x real
#define y imag

#define EPS (1e-10)
int sgn(ld val) {
    return (val < -EPS ? -1 : (val > EPS ? 1 : 0));
}
// 内積
ld dot(Vec a, Vec b) {
    return a.x() * b.x() + a.y() * b.y();
}
// 外積
ld crs(Vec a, Vec b) {
    return a.x() * b.y() - a.y() * b.x();
}
// 点の進行方向
#define CCW (1)
#define CW (-1)
#define OLB (2)
#define OLF (-2)
#define OS (0)
int isp(Point p0, Point p1, Point p2) {
    Vec a = p1 - p0;
    Vec b = p2 - p0;
    int val = sgn(crs(a,b));
    if (val > 0) return CCW;
    if (val < 0) return CW;
    if (sgn(dot(a,b)) < 0) return OLB;
    if (sgn(norm(a) - norm(b)) < 0) return OLF;
    return OS;
}

int n;
Polygon g;
ld area(ld e, array<ld,3> offset, array<int,3> vert) {
    array<Vec, 3> vec;
    for (int i = 0; i < 3; ++i) {
        int j = vert[i];
        int k = (j + 1) % n;
        vec[i] = (g[k] - g[j]) / abs(g[k] - g[j]) * (offset[i] + e) + g[j];
        // dbg(vec[i])
    }
    // triangle
    Vec a = vec[1] - vec[0];
    Vec b = vec[2] - vec[0];
    ld ans = abs(crs(a,b)) / 2;
    return ans;
}

ld solve() {
    array<int,3> a;
    cin >> n >> a[0] >> a[1] >> a[2];
    if (n+a[0]+a[1]+a[2] == 0) exit(0);
    for (int j = 0; j < 3; ++j) --a[j];
    g.resize(n);
    for (int i = 0; i < n; ++i) {
        int xx,yy;
        cin >> xx >> yy;
        g[i] = Point(xx,yy);
    }

    array<int,3> pos = a;
    array<ld,3> offset = {0,0,0};
    ld ans = 1e10;
    for (int z = 0; z < 3*n; ++z) {
        ld t = 1e10;
        int midx = -1;
        for (int i = 0; i < 3; ++i) {
            int j = pos[i];
            int k = (j + 1) % n;
            ld val = abs(g[k] - g[j]) - offset[i];
            if (sgn(val - t) < 0) {
                t = val;
                midx = i;
            }
        }
        // print(ALL(pos));
        // dbg(t)
        // dbg(midx);
        // [0, t]の範囲で三分探索
        ld l = 0, r = t;
        while (sgn(r - l) > 0) {
            ld c1 = (l + l + r) / 3;
            ld c2 = (l + r + r) / 3;
            ld a1 = area(c1, offset, pos);
            ld a2 = area(c2, offset, pos);
            if (sgn(a1 - a2) <= 0) r = c2;
            else l = c1;
        }
        ans = min(ans, area(l, offset, pos));

        // 位置の更新
        for (int i = 0; i < 3; ++i) {
            int j = pos[i];
            int k = (j + 1) % n;
            ld len = abs(g[k] - g[j]);
            if (sgn(len - (t + offset[i])) > 0) {
                offset[i] += t;
            } else if (sgn(len - (t + offset[i])) == 0) {
                offset[i] = 0;
                pos[i] = k;
            } else {
                pos[i] = k;
                offset[i] += (t + offset[i]) - len;
            }
        }
    }
    return ans;
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20); cerr << fixed << setprecision(6);
    while (true) {
        // solve();
        cout << solve() << '\n';
        // cout << (solve() ? "Yes" : "No") << '\n';
    }
}
accuracy: 1
time_ms: 340
memory_kb: 3672
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
#define all(A) A.begin(),A.end()
#define ALL(A) A.begin(),A.end()
#define rep(i, n) for (ll i = 0; i < (ll) (n); i++)
template<class T>
bool chmax(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p < q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

template<class T>
bool chmin(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p > q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

#include<complex>
const int INF = 1000000000;
const ll LINF = 1001002003004005006ll;
int dx[] = { 1,0,-1,0 }, dy[] = { 0,1,0,-1 };

struct IOSetup {
    IOSetup() {
        cin.tie(0);
        ios::sync_with_stdio(0);
        cout << fixed << setprecision(12);
    }
} iosetup;

template<typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    return os;
}
template<typename T>
istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v)is >> x;
    return is;
}

// line 1 "Geometry/template.cpp"
// Real
using Real = double;
const Real EPS = 1e-6;
const Real pi = acosl(-1);

// Point
using Point = complex<Real>;
istream& operator>>(istream& is, Point& p) {
    Real a, b;
    is >> a >> b;
    p = Point(a, b);
    return is;
}
ostream& operator<<(ostream& os, Point& p) {
    return os << fixed << setprecision(12) << p.real() << ' ' << p.imag();
}
inline bool eq(Real a, Real b) {
    return fabs(a - b) < EPS;
}
Point operator*(const Point& p, const Real& d) {
    return Point(real(p) * d, imag(p) * d);
}

// Line
struct Line {
    Point p1, p2;
    Line() = default;
    Line(Point p1, Point p2) :p1(p1), p2(p2) {}
    //Ax + By = C
    Line(Real A, Real B, Real C) {
        if (eq(A, 0))     p1 = Point(0, C / B), p2 = Point(1, C / B);
        else if (eq(B, 0))p1 = Point(C / A, 0), p2 = Point(C / A, 1);
        else            p1 = Point(0, C / B), p2 = Point(C / A, 0);
    }
};

// Segment
struct Segment :Line {
    Segment() = default;
    Segment(Point p1, Point p2) :Line(p1, p2) {}
};
Real dot(Point a, Point b) {
    return real(a) * real(b) + imag(a) * imag(b);
}
Real cross(Point a, Point b) {
    return real(a) * imag(b) - imag(a) * real(b);
}
int ccw(Point a, Point b, Point c) {
    b -= a; c -= a;
    if (cross(b, c) > EPS)       return  1;//COUNTER CLOCKWISE
    else if (cross(b, c) < -EPS) return -1;//CLOCKWISE
    else if (dot(b, c) < 0)      return  2;//c--a--b ONLINE BACK
    else if (norm(b) < norm(c)) return -2;//a--b--c ONLINE FRONT
    else                     return  0;//a--c--b ON SEGMENT
}
Point projection(Segment l, Point p) {
    Real k = dot(l.p1 - l.p2, p - l.p1) / norm(l.p1 - l.p2);
    return l.p1 + (l.p1 - l.p2) * k;
}
bool intersect(Segment s, Point p) {
    return ccw(s.p1, s.p2, p) == 0;
}
Real dis(Point a, Point b) {
    return abs(a - b);
}
Real dis(Segment s, Point p) {
    Point r = projection(s, p);
    if (intersect(s, r)) return abs(r - p);
    return min(abs(s.p1 - p), abs(s.p2 - p));
}

double area(Point P, Point Q, Point R) {
    Q -= P;
    R -= P;
    return abs(Q.imag() * R.real() - Q.real() * R.imag()) / 2.0;
}


double min_point(Point P, Point VP, Point Q, Point VQ, Point R, Point VR) {
    double L = 0.0, RR = 1.0;
    double A1;
    rep(i, 100) {
        double c1 = (L * 2.0 + RR) / 3.0;
        double c2 = (L + 2.0 * RR) / 3.0;
        A1 = area((1.0 - c1) * P + c1 * VP, (1.0 - c1) * Q + c1 * VQ, (1.0 - c1) * R + c1 * VR);
        double A2 = area((1.0 - c2) * P + c2 * VP, (1.0 - c2) * Q + c2 * VQ, (1.0 - c2) * R + c2 * VR);
        if (A1 < A2) {
            RR = c2;
        }
        else L = c1;
    }
    return A1;
}

void solve(ll N, ll p, ll q, ll r) {

    double an = 1e18;

    vector<Point> P(N);
    rep(i, N)cin >> P[i];
    priority_queue<pair<double, ll>, vector<pair<double, ll>>, greater<pair<double, ll>>> Q;
    Q.push({ dis(P[p],P[(p + 1) % N]),0 });
    Q.push({ dis(P[q],P[(q + 1) % N]),1 });
    Q.push({ dis(P[r],P[(r + 1) % N]),2 });
    vll NW = { p,q,r };
    vector<Point> NP = { P[p],P[q],P[r] };
    double NT = 0.0;
    rep(i, 5 * N) {
        double ET = Q.top().first;
        ll id = Q.top().second;
        Q.pop();
        double dt = ET - NT;

        vector<Point> nextP(3);
        rep(j, 3) {
            ll jd = NW[j];
            Point DP = P[(jd + 1) % N] - P[jd];
            double nm = abs(DP);
            nextP[j] = NP[j] + DP * dt / nm;
        }
        an = min(an, min_point(NP[0], nextP[0], NP[1], nextP[1], NP[2], nextP[2]));
        swap(NP, nextP);
        NW[id] = (NW[id] + 1) % N;
        NT = ET;
        Q.push({ ET+dis(NP[id],P[(NW[id]+1)%N]),id });
    }

    cout << an << endl;
    return;
}


int main() {

    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    ll N, p, q, r;
    while (cin >> N >> p >> q >> r, N != 0)solve(N, p - 1, q - 1, r - 1);

}
accuracy: 1
time_ms: 60
memory_kb: 3608
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#define all(a) a.begin(),a.end()
#define rep(i,n) for(int i=0;i<(n);i++)
using namespace std;
const double eps=1e-11;
double dist(double x1,double y1,double x2,double y2){
    double dx=x1-x2,dy=y1-y2;
    return sqrt(dx*dx+dy*dy);
}

double area(double x1,double y1,double x2,double y2){
    return abs((x1*y2-x2*y1)/2);
}

double get_min(double xp1,double yp1,double xq1,double yq1,double xr1,double yr1,double xp2,double yp2,double xq2,double yq2,double xr2,double yr2){
    xq1-=xp1;
    yq1-=yp1;
    xr1-=xp1;
    yr1-=yp1;
    xq2-=xp2;
    yq2-=yp2;
    xr2-=xp2;
    yr2-=yp2;
    double vxq=xq2-xq1,vyq=yq2-yq1,vxr=xr2-xr1,vyr=yr2-yr1;
    double lb=0,ub=1;
    double larea=area(xq1,yq1,xr1,yr1);
    double rarea=area(xq2,yq2,xr2,yr2);
    double marea=area(xq1+vxq/2,yq1+vyq/2,xr1+vxr/2,yr1+vyr/2);
    if(larea+rarea<=2*marea)return min(larea,rarea);
    rep(i,100){
        double mi1=(lb*2+ub)/3,mi2=(lb+ub*2)/3;
        double area1=area(xq1+mi1*vxq,yq1+mi1*vyq,xr1+mi1*vxr,yr1+mi1*vyr);
        double area2=area(xq1+mi2*vxq,yq1+mi2*vyq,xr1+mi2*vxr,yr1+mi2*vyr);
        if(area1+eps<area2)ub=mi2;
        else lb=mi1;
    }
    double area1=area(xq1+lb*vxq,yq1+lb*vyq,xr1+lb*vxr,yr1+lb*vyr);
    return area1;
}

void solve(int n,int kp,int kq,int kr){
    vector<int>x(n),y(n);
    rep(i,n)cin>>x[i]>>y[i];
    kp--;kq--;kr--;
    x.push_back(x[0]);y.push_back(y[0]);
    double ans=1e18;
    double xp=x[kp],yp=y[kp],xq=x[kq],yq=y[kq],xr=x[kr],yr=y[kr];
    int ep=kp,eq=kq,er=kr;

    rep(i,4*n){
        double to_next_p=dist(xp,yp,x[ep+1],y[ep+1]);
        double to_next_q=dist(xq,yq,x[eq+1],y[eq+1]);
        double to_next_r=dist(xr,yr,x[er+1],y[er+1]);
        double t=min({to_next_p,to_next_q,to_next_r});
        double vxp=(x[ep+1]-x[ep])/dist(x[ep],y[ep],x[ep+1],y[ep+1]);
        double vyp=(y[ep+1]-y[ep])/dist(x[ep],y[ep],x[ep+1],y[ep+1]);
        double vxq=(x[eq+1]-x[eq])/dist(x[eq],y[eq],x[eq+1],y[eq+1]);
        double vyq=(y[eq+1]-y[eq])/dist(x[eq],y[eq],x[eq+1],y[eq+1]);
        double vxr=(x[er+1]-x[er])/dist(x[er],y[er],x[er+1],y[er+1]);
        double vyr=(y[er+1]-y[er])/dist(x[er],y[er],x[er+1],y[er+1]);
        double xpn=xp+vxp*t;
        double ypn=yp+vyp*t;
        double xqn=xq+vxq*t;
        double yqn=yq+vyq*t;
        double xrn=xr+vxr*t;
        double yrn=yr+vyr*t;
        ans=min(ans,get_min(xp,yp,xq,yq,xr,yr,xpn,ypn,xqn,yqn,xrn,yrn));
        xp=xpn;yp=ypn;xq=xqn;yq=yqn;xr=xrn;yr=yrn;
        if(to_next_p<=to_next_q&&to_next_p<=to_next_r){
            ep=(ep+1)%n;
            xp=x[ep];yp=y[ep];
        }
        if(to_next_q<=to_next_p&&to_next_q<=to_next_r){
            eq=(eq+1)%n;
            xq=x[eq];yq=y[eq];
        }
        if(to_next_r<=to_next_p&&to_next_r<=to_next_q){
            er=(er+1)%n;
            xr=x[er];yr=y[er];
        }
    }
    printf("%.9lf\n",ans);
}

int main(){
	int n,kp,kq,kr;
    while(1){
        cin>>n>>kp>>kq>>kr;
        if(n==0)return 0;
        solve(n,kp,kq,kr);
    }
}
accuracy: 1
time_ms: 40
memory_kb: 3596
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;

using Point=complex<double>;

int solve(){
    int N;
    cin>>N;
    vector<int>K(3);
    for(int t=0;t<3;t++){
        cin>>K[t];
        K[t]--;
    }
    if(N==0)return 0;
    vector<int>X(N),Y(N);
    for(int i=0;i<N;i++)cin>>X[i]>>Y[i];
    vector<Point>vp(N);
    for(int i=0;i<N;i++)vp[i]=Point(X[i],Y[i]);
    vector<pair<double,int>>tm;
    tm.push_back(make_pair(0.0,-1));
    for(int t=0;t<3;t++){
        double cnt=0.0;
        for(int i=0;i<N;i++){
            double d=abs(vp[(K[t]+i+1)%N]-vp[(K[t]+i)%N]);
            cnt+=d;
            tm.push_back(make_pair(cnt,t));
        }
    }
    sort(tm.begin(),tm.end());
    int sz=tm.size();
    vector<int>at(3);
    vector<Point>now(3);
    for(int t=0;t<3;t++){
        at[t]=K[t];
        now[t]=vp[at[t]];
    }
    double ans=1e18;
    auto area=[&](double p,double q)-> double {
        vector<Point>now2(3);
        for(int t=0;t<3;t++){
            double d=abs(vp[(at[t]+1)%N]-vp[at[t]]);
            double ex=vp[(at[t]+1)%N].real()-vp[at[t]].real();
            double ey=vp[(at[t]+1)%N].imag()-vp[at[t]].imag();
            now2[t]=Point(now[t].real()+ex*(q-p)/d,now[t].imag()+ey*(q-p)/d);
        }
        for(int t=1;t<3;t++)now2[t]-=now2[0];
        return abs(now2[1].real()*now2[2].imag()-now2[1].imag()*now2[2].real())*0.5;
    };
    for(int i=0;i<sz-1;i++){
        double le=tm[i].first,ri=tm[i+1].first;
        for(int p=0;p<100;p++){
            double ml=(2*le+ri)/3.0,mr=(le+2*ri)/3.0;
            if(area(tm[i].first,ml)>area(tm[i].first,mr))le=ml;
            else ri=mr;
        }
        ans=min(ans,area(tm[i].first,(le+ri)/2.0));
        for(int t=0;t<3;t++){
            double d=abs(vp[(at[t]+1)%N]-vp[at[t]]);
            double ex=vp[(at[t]+1)%N].real()-vp[at[t]].real();
            double ey=vp[(at[t]+1)%N].imag()-vp[at[t]].imag();
            now[t]=Point(now[t].real()+ex*(tm[i+1].first-tm[i].first)/d,now[t].imag()+ey*(tm[i+1].first-tm[i].first)/d);
        }
        at[tm[i+1].second]=(at[tm[i+1].second]+1)%N;
    }
    cout<<ans<<endl;
    return 1;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout<<fixed<<setprecision(15);
    while(solve());
}
accuracy: 1
time_ms: 230
memory_kb: 3728
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (long long i = 0; i < (long long)(n); i++)
#define rrep(i,start,end) for (long long i = start;i >= (long long)(end);i--)
#define repn(i,end) for(long long i = 0; i <= (long long)(end); i++)
#define reps(i,start,end) for(long long i = start; i < (long long)(end); i++)
#define repsn(i,start,end) for(long long i = start; i <= (long long)(end); i++)
#define each(p,a) for(auto &p:a)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<long long> vll;
typedef vector<pair<long long ,long long>> vpll;
typedef vector<vector<long long>> vvll;
typedef set<ll> sll;
typedef map<long long , long long> mpll;
typedef pair<long long ,long long> pll;
typedef tuple<long long , long long , long long> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (int)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1LL << 60;
const ld EPS = 1e-9;
 
inline ll lfloor(ll x,ll m){return (x - ((x % m+ m)%m))/m;}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

// for AOJ or ICPC or etc..
// 全部が0だったらtrueを返す
template<class Tp> bool zero (const Tp &x) {return x == 0;}
template<class Tp, class... Args> bool zero (const Tp &x, const Args& ...args) {return zero(x) and zero(args...);}



//参考 https://github.com/saphmitchy/deliair-lib
// 型名
// R:Real, P:Point, L:Line, S:Segment, C:Circle, VP:vector<Point>

#define X(p) real(p)
#define Y(p) imag(p)

using R = ld;
using P = complex<R>;
using VP = vector<P>;

//const R EPS = 1e-9; // ここは適宜調節する,いつものやつから消す
const R pi = acos(-1.0);

int sgn(R a) {
    return (a < -EPS) ? -1 : (a > EPS) ? 1 : 0;
} // 符号関数

bool eq(R a, R b) {//実数の一致判定
    return sgn(b - a) == 0;
}

P operator*(P p, R d) {//ベクトルのd倍
    return P(X(p) * d, Y(p) * d);
}

P operator/(P p, R d) {//ベクトルの1/d倍
    return p * (1 / d);
}

istream &operator>>(istream &is, P &p) {
    // R a, b; // 入力が小数
    int a, b; // 入力が整数
    is >> a >> b;
    p = P(a, b);
    return is;
}

ostream &operator<<(ostream &os, P p) {
    return os << X(p) << ' ' << Y(p);
}

R getarg(P b,P a){//ベクトルbはベクトルaを何radian回転させる必要があるか
  assert(sgn(abs(a)) != 0);//長さが0はだめ
  return arg(b/a);
}

bool cp_x(P p, P q) {//ベクトルの比較x軸で比較->y軸で比較
    if (!eq(X(p), X(q)))
        return X(p) < X(q);
    return Y(p) < Y(q);
}

bool cp_y(P p, P q) {//ベクトルの比較y軸で比較->x軸で比較
    if (!eq(Y(p), Y(q)))
        return Y(p) < Y(q);
    return X(p) < X(q);
}

struct L {//直線ab
    P a, b;
    L() {}
    L(P a, P b) : a(a), b(b) {}

    // 入出力（必要なら）
    friend ostream &operator<<(ostream &os, L &l) {
        return os << l.a << ' ' << l.b;
    }
    friend istream &operator>>(istream &is, L &l) {
        return is >> l.a >> l.b;
    }
};

struct S : L {//線分ab
    S() {}
    S(P a, P b) : L(a, b) {}
};

struct C {//中心p 半径rの円
    P p;
    R r;
    C() {}
    C(P p, R r) : p(p), r(r) {}
};

P rot(P p, R t) {//ベクトルの回転
    return p * P(cos(t), sin(t));
}

//2つのベクトルの内積
R dot(P p, P q) {
    return X(p) * X(q) + Y(p) * Y(q);
}

//2つのベクトルの外積
R det(P p, P q) {
    return X(p) * Y(q) - Y(p) * X(q);
}

// https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C&lang=jp
int ccw(P a, P b, P c) { // 線分 ab に対する c の位置関係 
    b -= a, c -= a;//ベクトルab,ベクトルacにした
    if (sgn(det(b, c)) == 1)//外積右ねじ正
        return +1; // COUNTER_CLOCKWISE a,b,cが反時計回り
    if (sgn(det(b, c)) == -1)
        return -1; // CLOCKWISE
    if (dot(b, c) < 0.0)
        return +2; // ONLINE_BACK
    if (norm(b) < norm(c))
        return -2; // ONLINE_FRONT
    return 0;      // ON_SEGMENT
}

bool para(L a, L b) { // 平行判定
    return eq(det(a.b - a.a, b.b - b.a), 0.0);
}

bool orth(L a, L b) { // 垂直判定
    return eq(dot(a.b - a.a, b.b - b.a), 0.0);
}

P proj(L l, P p) { // 垂線の足
    R t = dot(p - l.a, l.b - l.a) / norm(l.b - l.a);
    return l.a + (l.b - l.a) * t;
}

// これいる？
// P proj(S s, P p) {
//     R t = dot(p - s.a, s.b - s.a) / norm(s.b - s.a);
//     return s.a + (s.b - s.a) * t;
// }

P refl(L l, P p) { // 線対称の位置にある点
    return p + (proj(l, p) - p) * 2.0;
}

bool inter(L l, P p) { // 交点を持つか判定
    return abs(ccw(l.a, l.b, p)) != 1;
}

bool inter(S s, P p) {
    return ccw(s.a, s.b, p) == 0;
}

bool inter(L l, L m) {
    if (!eq(det(l.b - l.a, m.b - m.a), 0.0))
        return true;
    return eq(det(l.b - l.a, m.b - l.a), 0.0);
}

bool inter(L l, S s) {
    return sgn(det(l.b - l.a, s.a - l.a) * det(l.b - l.a, s.b - l.a)) <= 0;
}

bool inter(S s, L l) {
    return inter(l, s);
}

bool inter(S s, S t) {
    if (ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) > 0)
        return false;
    return ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

R dist(P p, P q) {
    return abs(q - p);
}

R dist(L l, P p) {
    return abs(p - P(proj(l, p)));
}

R dist(S s, P p) {
    P h = proj(s, p);
    if (inter(s, h))
        return abs(h - p);
    return min(abs(s.a - p), abs(s.b - p));
}

R dist(L l, L m) {
    return inter(l, m) ? 0.0 : dist(l, m.a);
}

R dist(S s, S t) {
    if (inter(s, t))
        return 0.0;
    return min({dist(s, t.a), dist(s, t.b), dist(t, s.a), dist(t, s.b)});
}

R dist(L l, S s) {
    if (inter(l, s))
        return 0.0;
    return min(dist(l, s.a), dist(l, s.b));
}

R dist(S s, L l) {
    return dist(l, s);
}

bool inter(C c, L l) {
    return sgn(c.r - dist(l, c.p)) >= 0;
}

bool inter(C c, P p) {
    return eq(abs(p - c.p), c.r);
}

// 共通接線の本数
// 交点なし:4
// 外接:3
// 2点で交わる:2
// 内接:1
// 一方がもう一方を内包:0
int inter(C c1, C c2) {
    if (c1.r < c2.r)
        swap(c1, c2);
    R d = abs(c1.p - c2.p);
    int a = sgn(d - c1.r - c2.r);
    if (a >= 0)
        return 3 + a;
    return 1 + sgn(d - c1.r + c2.r);
}

VP crosspoint(L l, L m) {
    VP ret;
    if (!inter(l, m))
        return ret;
    R A = det(l.b - l.a, m.b - m.a);
    R B = det(l.b - l.a, l.b - m.a);
    if (eq(A, 0.0) && eq(B, 0.0)) {
        ret.emplace_back(m.a);
    } else {
        ret.emplace_back(m.a + (m.b - m.a) * B / A);
    }
    return ret;
}

VP crosspoint(S s, S t) {
    return inter(s, t) ? crosspoint(L(s), L(t)) : VP();
}

VP crosspoint(C c, L l) {//円と直線の交点
    P h = proj(l, c.p);
    P e = (l.b - l.a) / abs(l.b - l.a);
    VP ret;
    if (!inter(c, l))
        return ret;
    if (eq(dist(l, c.p), c.r)) {
        ret.emplace_back(h);
    } else {
        R b = sqrt(c.r * c.r - norm(h - c.p));
        ret.push_back(h + e * b), ret.push_back(h - e * b);
    }
    return ret;
}

VP crosspoint(C c, S s) {//円と線分の交点
    P h = proj(s, c.p);
    P e = (s.b - s.a) / abs(s.b - s.a);
    VP ret;
    if (!inter(c, s))
        return ret;
    if (eq(dist(s, c.p), c.r)) {
        ret.emplace_back(h);
    } else {
        R b = sqrt(c.r * c.r - norm(h - c.p));
        if(ccw(s.a,s.b,h - e * b) == 0){//s.aに近い方から線分上なら追加する
          ret.push_back(h - e * b);
        }
        if(ccw(s.a,s.b,h + e * b)==0){
          ret.push_back(h + e * b);
        }
    }
    return ret;
}

VP crosspoint(C c1, C c2) {//2つの円の交わる点
    R d = abs(c1.p - c2.p);
    R a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
    R t = atan2(Y(c2.p) - Y(c1.p), X(c2.p) - X(c1.p));
    VP ret;
    if (inter(c1, c2) % 4 == 0) // 交わらないとき
        return ret;
    if (eq(a, 0.0)) {
        ret.emplace_back(P(c1.p + rot(P(c1.r, 0.0), t)));
    } else {
        P p1 = c1.p + rot(P(c1.r, 0.0), t + a);
        P p2 = c1.p + rot(P(c1.r, 0.0), t - a);
        ret.emplace_back(p1), ret.emplace_back(p2);
    }
    return ret;
}

VP cut(VP p, L l, bool border = true) { // 直線が多角形に切り取られる区間
    int n = sz(p);
    p.emplace_back(p[0]), p.emplace_back(p[1]);
    VP ret;
    rep(i, n) {
        if (!eq(dist(l, p[i]), 0) && !eq(dist(l, p[i + 1]), 0)) {
            S s(p[i], p[i + 1]);
            if (eq(dist(l, s), 0)) {
                auto res = crosspoint(l, s);
                ret.emplace_back(res[0]);
            }
        }
        if (eq(dist(l, p[i + 1]), 0)) {
            if ((eq(dist(l, p[i]), 0) || eq(dist(l, p[i + 2]), 0)) && !border)
                continue;
            S s(p[i], p[i + 2]);
            if (eq(dist(l, s), 0))
                ret.emplace_back(p[i + 1]);
        }
    }
    return ret;
}

VP rectangle(S s, R r) { // sを軸とした幅rの長方形
    P d = (s.a - s.b) * P(0, 1);
    d *= r / sqrt(norm(d));
    return VP{s.a + d, s.a - d, s.b - d, s.b + d};
}

L vertical_bisector(P p, P q) { // 垂直二等分線
    L l;
    l.a = (p + q) * 0.5;
    l.b = l.a + rot(q - p, pi * 0.5);
    return l;
}

L angle_bisector(P a,P b,P c){//角abcの二等分線(角bの２等分線)
  L l;
  l.a = b;
  R ang = atan2(Y(c-b),X(c-b)) - atan2(Y(a-b),X(a-b));//なす角
  ang/=2.0;
  l.b = l.a + rot(a-b,ang);
  return l;
}

C Apollonius(P p, P q, R a, R b) { // アポロニウスの円
    P p1 = (p * b + q * a) / (a + b), p2 = (-p * b + q * a) / (a - b);
    C c;
    c.p = (p1 + p2) * 0.5;
    c.r = abs(p1 - p2) * 0.5;
    return c;
}

R area(VP p) { // 多角形の面積
    R ret = 0.0;
    int n = sz(p);
    rep(i, n) ret += det(p[i], p[(i + 1) % n]);
    return abs(ret * 0.5);
}

int in_polygon(VP p, P q) { // IN:2, ON:1, OUT:0
    int n = sz(p);
    int ret = 0;
    rep(i, n) {
        P a = p[i] - q, b = p[(i + 1) % n] - q;
        if (eq(det(a, b), 0.0) && sgn(dot(a, b)) <= 0)
            return 1;
        if (Y(a) > Y(b))
            swap(a, b);
        if (sgn(Y(a)) <= 0 && sgn(Y(b)) == 1 && sgn(det(a, b)) == 1)
            ret ^= 2;
    }
    return ret;
}

VP tangent(C c, P p) { // 点 p を通る円 c の接線と c の接点
    return crosspoint(c, C(p, sqrt(norm(p - c.p) - c.r * c.r)));
}

vector<L> tangent(C c1, C c2) { // 共通接線
    vector<L> ret;
    if (c1.r < c2.r)
        swap(c1, c2);
    R r = abs(c2.p - c1.p);
    if (eq(r, 0.0))
        return ret;
    P u = (c2.p - c1.p) / r;
    P v = rot(u, pi * 0.5);
    for (R s : {1.0, -1.0}) {
        R h = (c1.r + c2.r * s) / r;
        if (eq(abs(h), 1.0)) {
            ret.emplace_back(c1.p + u * c1.r, c1.p + (u + v) * c1.r);
        } else if (abs(h) < 1.0) {
            P uu = u * h, vv = v * sqrt(1.0 - h * h);
            ret.emplace_back(c1.p + (uu + vv) * c1.r, c2.p - (uu + vv) * c2.r * s);
            ret.emplace_back(c1.p + (uu - vv) * c1.r, c2.p - (uu - vv) * c2.r * s);
        }
    }
    return ret;
}

VP convex_hull(VP p) { // 凸包
    sort(all(p), cp_x);
    p.erase(unique(all(p)), end(p));
    int n = sz(p), k = 0;
    if (n == 1)
        return p;
    VP ch(2 * n);
    for (int i = 0; i < n; ch[k++] = p[i++]) {
        while (k >= 2 && sgn(det(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1])) <= 0)
            k--;
    }
    for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) {
        while (k >= t && sgn(det(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1])) <= 0)
            k--;
    }
    ch.resize(k - 1);
    return ch;
}

R closest_pair(VP p) { // 最近点対の距離
    if (sz(p) <= 1)
        return 1e18;
    sort(all(p), cp_x);
    VP memo(sz(p));

    function<R(int, int)> rec = [&](int l, int r) {
        if (r - l <= 1)
            return R(1e18);
        int m = (l + r) >> 1;
        R x = X(p[m]);
        R ret = min(rec(l, m), rec(m, r));
        inplace_merge(p.begin() + l, p.begin() + m, p.begin() + r, cp_y);
        int cnt = 0;
        reps(i, l, r) {
            if (abs(X(p[i]) - x) >= ret)
                continue;
            rep(j, cnt) {
                P d = p[i] - memo[cnt - j - 1];
                if (Y(d) >= ret)
                    break;
                chmin(ret, abs(d));
            }
            memo[cnt++] = p[i];
        }
        return ret;
    };

    return rec(0, sz(p));
}

R farthest_pair(VP p) {//最遠点対の距離
  VP ps = convex_hull(p);
  ll n = ps.size();
  if(n == 2){//凸包が潰れてる
    return dist(ps[0],ps[1]);
  }
  ll i = 0,j = 0;
  rep(k,n){//x軸方向に最も遠い点対を求める
    if(cp_x(ps[k],ps[i]))i = k;
    if(cp_x(ps[j],ps[k]))j = k;
  }
  R ret = 0;
  ll si = i,sj = j;
  while(i != sj || j != si){//180度反転しきるまで
    ret = max(ret,dist(ps[i],ps[j]));
    if(det(ps[(i+1)%n] - ps[i],ps[(j+1)%n]-ps[j]) < 0){
      i = (i + 1) % n;
    }else{
      j = (j + 1) % n;
    }
  }
  return ret;
}

// 原点, 点 a, 点 b とで囲まれる領域の面積 (三角形 ver と扇型 ver)
R calc_element(P a, P b, R cr,bool triangle){
  if(triangle)return det(a,b)/2;
  else{
    P tmp = b * (P(X(a),-Y(a)));
    R ang = atan2(Y(tmp),X(tmp));
    return cr * cr * ang/2;
  }
}

// 円 C と、三角形 ((0, 0), ia, ib) との共通部分の面積
R common_area(C c, P ia,P ib){
  P a = ia - c.p , b = ib - c.p;
  if(eq(abs(a-b),0))return 0;
  bool isin_a = (sgn(c.r - abs(a))>= 0);
  bool isin_b = (sgn(c.r - abs(b))>= 0);
  if(isin_a && isin_b)return calc_element(a,b,c.r,true);//aもbも円の中

  C oc(P(0,0),c.r);
  S seg(a,b);
  VP cr = crosspoint(oc,seg);
  if(cr.empty())return calc_element(a,b,c.r,false);
  P s = cr[0],t = cr.back();
  return calc_element(s,t,c.r,true) + calc_element(a,s,c.r,isin_a) + calc_element(t,b,c.r,isin_b);

}


R common_area(C c, VP vp){// 円cと多角形の共通部分の面積
  R ret = 0;
  ll n = vp.size();
  rep(i,n){
    ret += common_area(c,vp[i],vp[(i+1)%n]);
  }
  return ret;
}

R common_area(C p, C q) {// 円と円の共通部分の面積
    R d = abs(p.p - q.p);
    if (d >= p.r + q.r - EPS) return 0;
    else if (d <= abs(p.r - q.r) + EPS) return min(p.r, q.r) * min(p.r, q.r) * pi;
    R pcos = (p.r*p.r + d*d - q.r*q.r) / (p.r*d*2);
    R pang = acosl(pcos);
    R parea = p.r*p.r*pang - p.r*p.r*sin(pang*2)/2;
    R qcos = (q.r*q.r + d*d - p.r*p.r) / (q.r*d*2);
    R qang = acosl(qcos);
    R qarea = q.r*q.r*qang - q.r*q.r*sin(qang*2)/2;
    return parea + qarea;
}

vector<VP> divisions(vector<L> lf, R lim = 1e9) {
    vector<L> ls;
    each(l, lf) {
        bool ok = true;
        each(m, ls) {
            if (para(l, m) & inter(l, m.a)) {
                ok = false;
                break;
            }
        }
        if (ok)
            ls.emplace_back(l);
    }
    VP lc{P(-lim, -lim), P(lim, -lim), P(lim, lim), P(-lim, lim)};
    rep(i, 4) ls.emplace_back(lc[i], lc[(i + 1) % 4]);
    int m = sz(ls);
    VP ps;
    vector<vector<int>> lp(m);
    rep(i, m) {
        reps(j, i + 1, m) {
            each(p, crosspoint(ls[i], ls[j])) {
                if (max(abs(X(p)), abs(Y(p))) < lim + EPS) {
                    lp[i].emplace_back(sz(ps)), lp[j].emplace_back(sz(ps));
                    ps.emplace_back(p);
                }
            }
        }
    }
    int n = sz(ps);
    vector<int> id(n, -1), to;
    vector<R> rg;
    vector<vector<pair<R, int>>> li(n);
    rep(i, m) {
        sort(all(lp[i]), [&ps](int a, int b) { return cp_x(ps[a], ps[b]); });
        vector<int> q;
        rep(j, sz(lp[i])) {
            int me = id[lp[i][j]], st = j;
            auto np = ps[lp[i][j]];
            while (j + 1 < sz(lp[i])) {
                if (abs(ps[lp[i][j + 1]] - np) < EPS) {
                    j++;
                    if (id[lp[i][j]] != -1)
                        me = id[lp[i][j]];
                } else
                    break;
            }
            if (me == -1)
                me = lp[i][st];
            reps(k, st, j + 1) id[lp[i][k]] = me;
            q.emplace_back(me);
        }
        rep(i, sz(q) - 1) {
            P d = ps[q[i + 1]] - ps[q[i]];
            R s = atan2(Y(d), X(d)), t = atan2(-Y(d), -X(d));
            int x = q[i], y = q[i + 1];
            li[x].emplace_back(s, sz(to));
            li[x].emplace_back(s + pi * 2, sz(to));
            to.emplace_back(y), rg.emplace_back(t);
            li[y].emplace_back(t, sz(to));
            li[y].emplace_back(t + pi * 2, sz(to));
            to.emplace_back(x), rg.emplace_back(s);
        }
    }
    rep(i, n) sort(all(li[i]));
    vector<bool> u(sz(to), false);
    vector<VP> ret;
    rep(i, n) {
        each(l, li[i]) {
            int ns = l.second;
            if (u[ns])
                continue;
            VP nv;
            int no = ns;
            bool ok = true;
            while (1) {
                if (sz(nv) > 1) {
                    P x = nv[sz(nv) - 2], y = nv[sz(nv) - 1], z = ps[to[no]];
                    int c = ccw(x, y, z);
                    if (c == 1)
                        ok = false;
                    if (c != -1)
                        nv.pop_back();
                }
                nv.emplace_back(ps[to[no]]);
                u[no] = true;
                no = upper_bound(all(li[to[no]]), pair(rg[no] + EPS, -1))->second;
                if (no == ns)
                    break;
            }
            if (ok)
                ret.emplace_back(nv);
        }
    }
    return ret;
}
//ref https://github.com/drken1215/algorithm/blob/master/Geometry/arg_sort.cpp
//verify https://atcoder.jp/contests/abc139/submissions/me
//点列を偏角ソート
void arg_sort(VP &v){
  //原点=0,(pi,2pi] = -1  (0pi,pi] = 1
  auto sign = [&](const P &p){
    if(sgn(X(p)) == 0 && sgn(Y(p)) == 0){
      return 0;
    }else if(sgn(Y(p)) == -1 || (sgn(Y(p)) == 0 && sgn(X(p)) == 1)){
      return -1;
    }else{
      return 1;
    }
  };
  auto cp = [&](const P &p,const P &q){
    if(sign(p) != sign(q)){
      return sign(p) < sign(q);
    }else{//外積>0で判定
      //同じ向きのときは未定義必要に応じて決める
      return X(p) * Y(q) - Y(p) * X(q) > 0;
    }
  };
  sort(v.begin(),v.end(),cp);
}


// 変数をちゃんと全部受け取る！
void solve(ll n,ll a,ll b,ll c){
  a--;b--;c--;
  VP vp(n);
  rep(i,n){
    LL(x,y);
    vp[i] = P(x,y);
  }
  vector<tuple<ld,ll,ll>> ord;//時間、どれか、頂点番号
  auto createord = [&](ll sta,ll v){
    R time = 0;
    ll now = sta;
    rep(i,n){
      ll id = (now +1) % n;
      time += dist(vp[id], vp[now]);
      ord.push_back({time,v,id});
      now = id;
    }
  };
  createord(a,0);createord(b,1);createord(c,2);
  sort(all(ord));

  ld ans = 9 * lpow(10,9);

  ll siz = ord.size();

  ld time = 0;
  vll plc ={a,b,c};
  VP vplc = {vp[a],vp[b],vp[c]};
  rep(i,siz){
    auto[ntime,v,idx] = ord[i];
    if(eq(ntime,time)){
      plc[v] = idx;
      vplc[v] = vp[idx];
      time = ntime ;
      continue;
    }
    //time->ntimeの面積を三分探索



    //3分探索、初期値は閉区間の端でいい
    ld l = time;//左端閉
    ld r = ntime;//右端閉
    P v0 = vp[(plc[0]+1) % n] - vp[plc[0]];
    P v1 = vp[(plc[1]+1) % n] - vp[plc[1]];
    P v2 = vp[(plc[2]+1) % n] - vp[plc[2]];
    auto f = [&](ld m1,ld m2)->bool{
      //m1のときの方がいい値かどうか

      VP pm1 = {vplc[0]+v0 * (m1 - time)/(abs(v0)),vplc[1]+v1 * (m1 - time)/(abs(v1)),vplc[2]+v2 * (m1 - time)/(abs(v2))};
      VP pm2 = {vplc[0]+v0 * (m2 - time)/(abs(v0)),vplc[1]+v1 * (m2 - time)/(abs(v1)),vplc[2]+v2 * (m2 - time)/(abs(v2))};
      return abs(area(pm1)) < abs(area(pm2));
    };
    //最終的な答えは離散値ならl,l+1,rのいづれかにある
    while(abs(l-r) > 1e-9){
      ld m1 = l + (r-l)/3;
      ld m2 = r - (r-l)/3;
      if(f(m1,m2)){
        //m1のほうがいい値だった
        r = m2;
      }else{
        l = m1;
      }
    }

    VP pml = {vplc[0]+v0 * (l - time)/(abs(v0)),vplc[1]+v1 * (l - time)/(abs(v1)),vplc[2]+v2 * (l - time)/(abs(v2))};
    chmin(ans,abs(area(pml)));
    plc[v] = idx;

    vplc[0] = vplc[0] + v0 * (ntime - time)/(abs(v0));
    vplc[1] = vplc[1] + v1 * (ntime - time)/(abs(v1));
    vplc[2] = vplc[2] + v2 * (ntime - time)/(abs(v2));
    vplc[v] = vp[idx];
    time = ntime;
  }
  cout <<std::fixed << std::setprecision(10) << ans << endl;
}
 
int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  while(true){
    LL(n,a,b,c);//変数数調整
    if(zero(n,a,b,c))break;
    solve(n,a,b,c);
  }
}
accuracy: 1
time_ms: 180
memory_kb: 3856
final_rank: 14

code_snippet: #include <bits/stdc++.h>

#include <algorithm>
#include <cmath>
#include <iterator>
#include <utility>
#include <vector>

using Real = long double;
constexpr Real EPS = 1e-10;
const Real PI = std::acos(-1);

int sign(Real x) {
    return x < -EPS ? -1 : x > EPS ? 1 : 0;
}

bool eq(Real lhs, Real rhs) {
    return sign(rhs - lhs) == 0;
}

bool lte(Real lhs, Real rhs) {
    return sign(rhs - lhs) >= 0;
}

bool lt(Real lhs, Real rhs) {
    return sign(rhs - lhs) > 0;
}

bool gte(Real lhs, Real rhs) {
    return lte(rhs, lhs);
}

bool gt(Real lhs, Real rhs) {
    return lt(rhs, lhs);
}

struct Point {
    Real x;
    Real y;
    Point(Real x = 0, Real y = 0): x(x), y(y) {}
    Point& operator+=(Point rhs) {
        this->x += rhs.x;
        this->y += rhs.y;
        return *this;
    }
    Point& operator-=(Point rhs) {
        this->x -= rhs.x;
        this->y -= rhs.y;
        return *this;
    }
    Point& operator*=(Real k) {
        this->x *= k;
        this->y *= k;
        return *this;
    }
    Point& operator/=(Real k) {
        this->x /= k;
        this->y /= k;
        return *this;
    }
    friend Point operator+(Point lhs, Point rhs) {
        return lhs += rhs;
    }
    friend Point operator-(Point lhs, Point rhs) {
        return lhs -= rhs;
    }
    friend Point operator*(Point p, Real k) {
        return p *= k;
    }
    friend Point operator/(Point p, Real k) {
        return p /= k;
    }
    friend Point operator*(Real k, Point p) {
        return p * k;
    }
    friend Point operator/(Real k, Point p) {
        return p / k;
    }
    friend bool operator==(Point lhs, Point rhs) {
        return eq(lhs.x, rhs.x) && eq(lhs.y, rhs.y);
    }
    friend bool operator<(Point lhs, Point rhs) {
        if (eq(lhs.x, rhs.x)) return lt(lhs.y, rhs.y);
        return lt(lhs.x, rhs.x);
    }
    friend bool operator>(Point lhs, Point rhs) {
        return rhs < lhs;
    }
};

using Points = std::vector<Point>;
using Polygon = Points;
using Vector = Point;

Real norm(Vector p) {
    return p.x * p.x + p.y * p.y;
}

Real abs(Vector p) {
    return std::sqrt(norm(p));
}

Real dot(Vector lhs, Vector rhs) {
    return lhs.x * rhs.x + lhs.y * rhs.y;
}

Real cross(Vector lhs, Vector rhs) {
    return lhs.x * rhs.y - lhs.y * rhs.x;
}

int ccw(Point p0, Point p1, Point p2) {
    Vector a = p1 - p0;
    Vector b = p2 - p0;

    if (cross(a, b) > EPS) return 1;

    if (cross(a, b) < -EPS) return -1;

    if (dot(a, b) < 0) return 2;

    if (norm(a) < norm(b)) return -2;

    return 0;
}

struct Circle {
    Real r;
    Point c;
    Circle() {}
    Circle(Real r, Point c): r(r), c(c) {}
};

struct Segment {
    Segment() {}
    Segment(Point p0, Point p1): p0(p0), p1(p1) {}
    Point p0, p1;
};

struct Line {
    Line() {}
    Line(Point p0, Point p1): p0(p0), p1(p1) {}
    explicit Line(Segment s): p0(s.p0), p1(s.p1) {}
    Point p0, p1;
};

Real distance(Point lhs, Point rhs) {
    return abs(rhs - lhs);
}

Real distance(Line l, Point p) {
    return std::abs(cross(l.p1 - l.p0, p - l.p0)) / abs(l.p1 - l.p0);
}

Real distance(Segment s, Point p) {
    if (dot(s.p1 - s.p0, p - s.p0) < 0) {
        return distance(p, s.p0);
    }
    if (dot(s.p0 - s.p1, p - s.p1) < 0) {
        return distance(p, s.p1);
    }
    return distance(Line(s), p);
}

bool intersect(Segment lhs, Segment rhs) {
    return ccw(lhs.p0, lhs.p1, rhs.p0) * ccw(lhs.p0, lhs.p1, rhs.p1) <= 0
           && ccw(rhs.p0, rhs.p1, lhs.p0) * ccw(rhs.p0, rhs.p1, lhs.p1) <= 0;
}

bool intersect(Segment s, Point p) {
    return ccw(s.p0, s.p1, p) == 0;
}

Real distance(Segment lhs, Segment rhs) {
    if (intersect(lhs, rhs)) {
        return Real(0);
    }
    return std::min({distance(lhs, rhs.p0), distance(lhs, rhs.p1), distance(rhs, lhs.p0), distance(rhs, lhs.p1)});
}

bool parallel(Vector lhs, Vector rhs) {
    return eq(cross(lhs, rhs), 0);
}

bool parallel(Segment lhs, Segment rhs) {
    return parallel(lhs.p0 - lhs.p1, rhs.p0 - rhs.p1);
}

bool parallel(Line lhs, Line rhs) {
    return parallel(lhs.p0 - lhs.p1, rhs.p0 - rhs.p1);
}

Point crosspoint(Line lhs, Line rhs) {
    Real a = cross(lhs.p1 - lhs.p0, rhs.p1 - rhs.p0);
    Real b = cross(lhs.p1 - lhs.p0, lhs.p1 - rhs.p0);
    return rhs.p0 + (rhs.p1 - rhs.p0) * b / a;
}

bool intersect(Line l, Segment s) {
    return ccw(l.p0, l.p1, s.p0) * ccw(l.p0, l.p1, s.p1) <= 0;
}

bool intersect(Circle c, Line l) {
    return lte(distance(l, c.c), c.r);
}

bool intersect(Circle c, Point p) {
    return eq(distance(c.c, p), c.r);
}

int intersect(Circle lhs, Circle rhs) {
    if (gt(lhs.r, rhs.r)) std::swap(lhs, rhs);
    Real d = distance(lhs.c, rhs.c);
    if (lt(lhs.r + rhs.r, d)) return 4;
    if (eq(lhs.r + rhs.r, d)) return 3;
    if (gt(lhs.r + d, rhs.r)) return 2;
    if (eq(lhs.r + d, rhs.r)) return 1;
    return 0;
}

bool orthogonal(Vector lhs, Vector rhs) {
    return eq(dot(lhs, rhs), 0);
}

bool orthogonal(Segment lhs, Segment rhs) {
    return orthogonal(lhs.p0 - lhs.p1, rhs.p0 - rhs.p1);
}

bool orthogonal(Line lhs, Line rhs) {
    return orthogonal(lhs.p0 - lhs.p1, rhs.p0 - rhs.p1);
}

Point crosspoint(Segment lhs, Segment rhs) {
    Real d0 = distance(Line(lhs.p0, lhs.p1), rhs.p0);
    Real d1 = distance(Line(lhs.p0, lhs.p1), rhs.p1);
    return rhs.p0 + (rhs.p1 - rhs.p0) * (d0 / (d0 + d1));
}

Real arg(Vector p) {
    return std::atan2(p.y, p.x);
}

Vector polar(Real a, Real r) {
    return Point(std::cos(r) * a, std::sin(r) * a);
}

Point rotate(Point p, Real t) {
    Point v = polar(1, t);
    return Point(p.x * v.x - p.y * v.y, p.x * v.y + p.y * v.x);
}

Real angle(Point p0, Point p1, Point p2) {
    Real a = arg(p0 - p1);
    Real b = arg(p2 - p1);
    if (gt(a, b)) std::swap(a, b);
    return std::min(b - a, 2 * PI - (b - a));
}

Points crosspoint(Circle lhs, Circle rhs) {
    Real d = abs(lhs.c - rhs.c);
    if (eq(d, lhs.r + rhs.r)) return {lhs.c + lhs.r * (rhs.c - lhs.c) / d};
    Real a = std::acos((lhs.r * lhs.r + d * d - rhs.r * rhs.r) / (2 * lhs.r * d));
    Real t = arg(rhs.c - lhs.c);
    return {lhs.c + polar(lhs.r, t + a), lhs.c + polar(lhs.r, t - a)};
}

Point projection(Segment s, Point p) {
    Vector a = p - s.p0;
    Vector b = s.p1 - s.p0;
    Real t = dot(a, b) / norm(b);
    return s.p0 + t * b;
}

Point projection(Line l, Point p) {
    Vector a = p - l.p0;
    Vector b = l.p1 - l.p0;
    Real t = dot(a, b) / norm(b);
    return l.p0 + t * b;
}

Point reflection(Segment s, Point p) {
    return p + (projection(s, p) - p) * Real(2);
}

Point reflection(Line l, Point p) {
    return p + (projection(l, p) - p) * Real(2);
}

Points crosspoint(Circle c, Line l) {
    Vector p = projection(l, c.c);
    Real t = std::sqrt(c.r * c.r - norm(c.c - p));
    if (eq(t, 0)) return {p};
    Vector e = (l.p1 - l.p0) / abs(l.p1 - l.p0);
    return {p + t * e, p + -t * e};
}

Real area(Polygon poly) {
    int n = poly.size();
    Real result = 0;
    for (int i = 0; i < n; i++) {
        result += cross(poly[i], poly[(i + 1) % n]);
    }
    return result / 2;
}

Real perimeter(Polygon poly) {
    int n = poly.size();
    Real result = 0;
    for (int i = 0; i < n; i++) {
        result += abs(poly[i] - poly[(i + 1) % n]);
    }
    return result;
}

bool convex(Polygon poly) {
    int n = poly.size();
    for (int i = 0; i < n; i++) {
        if (ccw(poly[i], poly[(i + 1) % n], poly[(i + 2) % n]) == -1) return false;
    }
    return true;
}

int contain(Polygon poly, Point p) {
    int n = poly.size();
    bool parity = false;
    for (int i = 0; i < n; i++) {
        Point a = poly[i] - p;
        Point b = poly[(i + 1) % n] - p;
        if (gt(a.y, b.y)) std::swap(a, b);
        if (lte(a.y, 0) && lt(0, b.y) && lt(cross(a, b), 0)) parity ^= true;
        if (eq(cross(a, b), 0) && lte(dot(a, b), 0)) return 1;
    }
    return (parity ? 2 : 0);
}

Polygon convex_hull(Points points) {
    std::sort(points.begin(), points.end(), [](Point lhs, Point rhs) {
        if (eq(lhs.x, rhs.x)) return lt(lhs.y, rhs.y);
        return lt(lhs.x, rhs.x);
    });
    int n = points.size();
    Points lower, upper;
    lower.push_back(points[n - 1]);
    lower.push_back(points[n - 2]);
    upper.push_back(points[0]);
    upper.push_back(points[1]);
    for (int i = n - 3; i >= 0; i--) {
        for (int m = lower.size(); m >= 2 && ccw(lower[m - 2], lower[m - 1], points[i]) >= 0; m--) {
            lower.pop_back();
        }
        lower.push_back(points[i]);
    }
    for (int i = 2; i < n; i++) {
        for (int m = upper.size(); m >= 2 && ccw(upper[m - 2], upper[m - 1], points[i]) >= 0; m--) {
            upper.pop_back();
        }
        upper.push_back(points[i]);
    }
    std::reverse(lower.begin(), lower.end());
    std::copy(std::next(upper.rbegin()), std::prev(upper.rend()), std::back_inserter(lower));
    return lower;
}

Polygon convex_cut(Polygon poly, Line l) {
    int n = poly.size();
    Polygon res;
    for (int i = 0; i < n; i++) {
        Point a = poly[i];
        Point b = poly[(i + 1) % n];
        if (ccw(l.p0, l.p1, a) != -1) res.push_back(a);
        if (ccw(l.p0, l.p1, a) * ccw(l.p0, l.p1, b) == -1) {
            res.push_back(crosspoint(l, Line(a, b)));
        }
    }
    return res;
}

Line bisector(Point p0, Point p1, Point p2) {
    return Line(p1, p1 + polar(1, angle(p0, p1, p2) / 2));
}

Circle incircle(Point p0, Point p1, Point p2) {
    Point c = crosspoint(bisector(p0, p1, p2), bisector(p1, p2, p0));
    Real r = std::abs(2 * area({p0, p1, p2}) / perimeter({p0, p1, p2}));
    return Circle(r, c);
}

Line perpendicular(Line l, Point p) {
    Vector v = l.p1 - l.p0;
    return Line(p, p + Vector(-v.y, v.x));
}

Line perpendicular_bisector(Segment s) {
    return perpendicular(Line(s), (s.p0 + s.p1) / 2);
}

Circle circumscribed_circle(Point p0, Point p1, Point p2) {
    Point c = crosspoint(perpendicular_bisector(Segment(p0, p1)), perpendicular_bisector(Segment(p0, p2)));
    return Circle(distance(p0, c), c);
}

Real area(Circle c) {
    return c.r * c.r * PI;
}

Points tangent(Circle c, Point p) {
    return crosspoint(c, Circle(std::sqrt(norm(c.c - p) - c.r * c.r), p));
}

Point div(Segment s, Real t) {
    return s.p0 + t * (s.p1 - s.p0);
}

const int ROOP = 100;
Real calc(std::vector<Segment> segments) {
    Real l = 0;
    Real r = 1;
    for (int loop = 0; loop < ROOP; loop++) {
        Real m1 = (2 * l + r) / 3;
        Real m2 = (l + 2 * r) / 3;
        std::vector<Real> areas;
        for (Real t: {m1, m2}) {
            Polygon poly;
            for (int i = 0; i < 3; i++) {
                poly.push_back(div(segments[i], t));
            }
            areas.push_back(std::abs(area(poly)));
        }
        if (areas[0] > areas[1])
            l = m1;
        else
            r = m2;
    }
    Polygon poly;
    for (int i = 0; i < 3; i++) {
        poly.push_back(div(segments[i], l));
    }
    return std::abs(area(poly));
}

int solve() {
    int n;
    std::cin >> n;
    std::vector<int> s(3);
    for (int i = 0; i < 3; i++) std::cin >> s[i], s[i]--;
    if (n == 0) return 1;
    Polygon polygon;
    for (int i = 0; i < n; i++) {
        Point p;
        std::cin >> p.x >> p.y;
        polygon.push_back(p);
    }
    using Segments = std::vector<Segment>;
    std::vector<Segments> segss(3);
    for (int i = 0; i < 3; i++) {
        Segments segs;
        for (int j = 0; j < n; j++) {
            Point a = polygon[(j + s[i]) % n];
            Point b = polygon[(j + s[i] + 1) % n];
            segs.push_back(Segment(a, b));
        }
        segss[i] = segs;
    }
    Real ans = 1e18;
    while (!segss.front().empty()) {
        Segments segs;
        for (int i = 0; i < 3; i++) {
            segs.push_back(segss[i].back());
            segss[i].pop_back();
        }
        std::vector<Real> lengths(3);
        for (int i = 0; i < 3; i++) lengths[i] = abs(segs[i].p1 - segs[i].p0);
        Real min_length = *std::min_element(lengths.begin(), lengths.end());
        Segments left, right;
        for (int i = 0; i < 3; i++) {
            Vector v = segs[i].p1 - segs[i].p0;
            Point mid = segs[i].p1 - min_length * v / abs(v);
            left.push_back(Segment(segs[i].p0, mid));
            right.push_back(Segment(mid, segs[i].p1));
        }

        ans = std::min(ans, calc(right));
        for (int i = 0; i < 3; i++) {
            Vector v = left[i].p1 - left[i].p0;
            if (eq(norm(v), 0)) continue;
            segss[i].push_back(left[i]);
        }
    }
    std::cout << std::fixed << std::setprecision(10);
    std::cout << ans << std::endl;
    return 0;
}

int main() {
    while (!solve())
        ;
}
accuracy: 1
time_ms: 430
memory_kb: 3652
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<ll, ll>;
#define rep(i, a, b) for(ll i = a; i < b; ++i)
#define rrep(i, a, b) for(ll i = a; i >= b; --i)
constexpr ll inf = 4e18;
struct SetupIO {
    SetupIO() {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout << fixed << setprecision(30);
    }
} setup_io;
using Real = long double;
const Real EPS = Real(1e-8), PI = acos(Real(-1.0));
int sign(const Real& r) {
    if(r <= -EPS) return -1;
    if(r >= +EPS) return +1;
    return 0;
}
bool eq(const Real& a, const Real& b) {
    return sign(a - b) == 0;
}
using Point = complex<Real>;
istream& operator>>(istream& is, Point& p) {
    Real a, b;
    is >> a >> b;
    p = Point(a, b);
    return is;
}
ostream& operator<<(ostream& os, const Point& p) {
    return os << p.real() << " " << p.imag();
}
Point operator*(const Point& p, const Real& d) {
    return Point(p.real() * d, p.imag() * d);
}
Point operator/(const Point& p, const Real& d) {
    return Point(p.real() / d, p.imag() / d);
}
Point rot(const Point& p, const Real& theta) {
    return p * Point(cos(theta), sin(theta));
}
Real dot(const Point& p1, const Point& p2) {
    return (conj(p1) * p2).real();
}
Real cross(const Point& p1, const Point& p2) {
    return (conj(p1) * p2).imag();
}
Real dist(const Point& p1, const Point& p2) {
    return abs(p1 - p2);
}
bool comp_x(const Point& p1, const Point& p2) {
    return eq(p1.real(), p2.real()) ? p1.imag() < p2.imag() : p1.real() < p2.real();
}
bool comp_y(const Point& p1, const Point& p2) {
    return eq(p1.imag(), p2.imag()) ? p1.real() < p2.real() : p1.imag() < p2.imag();
}
bool comp_arg(const Point& p1, const Point& p2) {
    return arg(p1) < arg(p2);
}
int ccw(const Point& a, Point b, Point c) {
    b -= a;
    c -= a;
    if(sign(cross(b, c)) == 1) return 1;
    if(sign(cross(b, c)) == -1) return -1;
    if(sign(dot(b, c)) == -1) return +2;
    if(norm(b) < norm(c)) return -2;
    return 0;
}
Real closest_pair(vector<Point> ps) {
    if((int)ps.size() <= 1) return Real(1e18);
    sort(ps.begin(), ps.end(), comp_x);
    vector<Point> memo(ps.size());
    auto func = [&](auto& func, int l, int r) -> Real {
        if(r - l <= 1) return Real(1e18);
        int m = (l + r) >> 1;
        Real x = ps[m].real();
        Real res = min(func(func, l, m), func(func, m, r));
        inplace_merge(ps.begin() + l, ps.begin() + m, ps.begin() + r, comp_y);
        int cnt = 0;
        for(int i = l; i < r; ++i) {
            if(abs(ps[i].real() - x) >= res) continue;
            for(int j = 0; j < cnt; ++j) {
                Point d = ps[i] - memo[cnt - j - 1];
                if(d.imag() >= res) break;
                res = min(res, abs(d));
            }
            memo[cnt++] = ps[i];
        }
        return res;
    };
    return func(func, 0, (int)ps.size());
}
struct Line {
    Point a, b;
    Line() = default;
    Line(const Point& a, const Point& b)
        : a(a), b(b) {}
};
using Segment = Line;
bool is_parallel(const Line& a, const Line& b) {
    return eq(cross(a.b - a.a, b.b - b.a), 0.0);
}
bool is_orthogonal(const Line& a, const Line& b) {
    return eq(dot(a.b - a.a, b.b - b.a), 0.0);
}
Point projection(const Line& l, const Point& p) {
    Real t = dot(p - l.a, l.b - l.a) / norm(l.b - l.a);
    return l.a + (l.b - l.a) * t;
}
Point reflection(const Line& l, const Point& p) {
    return p + (projection(l, p) - p) * 2.0;
}
bool is_intersect_lp(const Line& l, const Point& p) {
    return abs(ccw(l.a, l.b, p)) != 1;
}
bool is_intersect_sp(const Segment& s, const Point& p) {
    return ccw(s.a, s.b, p) == 0;
}
bool is_intersect_ll(const Line& l1, const Line& l2) {
    if(!eq(cross(l1.b - l1.a, l2.b - l2.a), 0.0)) return true;
    return eq(cross(l1.b - l1.a, l2.b - l1.a), 0.0);
}
bool is_intersect_ls(const Line& l, const Segment& s) {
    return sign(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a)) <= 0;
}
bool is_intersect_sl(const Segment& s, const Line& l) {
    return is_intersect_ls(l, s);
}
bool is_intersect_ss(const Segment& s1, const Segment& s2) {
    if(ccw(s1.a, s1.b, s2.a) * ccw(s1.a, s1.b, s2.b) > 0) return false;
    return ccw(s2.a, s2.b, s1.a) * ccw(s2.a, s2.b, s1.b) <= 0;
}
vector<Point> intersection_ll(const Line& l1, const Line& l2) {
    vector<Point> res;
    if(!is_intersect_ll(l1, l2)) return res;
    Real a = cross(l1.b - l1.a, l2.b - l2.a);
    Real b = cross(l1.b - l1.a, l1.b - l2.a);
    if(eq(a, 0.0) and eq(b, 0.0)) {
        res.emplace_back(l2.a);
    } else {
        res.emplace_back(l2.a + (l2.b - l2.a) * b / a);
    }
    return res;
}
vector<Point> intersection_ss(const Segment& s1, const Segment& s2) {
    return is_intersect_ss(s1, s2) ? intersection_ll(Line(s1), Line(s2)) : vector<Point>();
}
Real dist_lp(const Line& l, const Point& p) {
    return abs(p - projection(l, p));
}
Real dist_sp(const Segment& s, const Point& p) {
    const Point h = projection(s, p);
    if(is_intersect_sp(s, h)) return abs(h - p);
    return min(abs(s.a - p), abs(s.b - p));
}
Real dist_ll(const Line& l1, const Line& l2) {
    if(is_intersect_ll(l1, l2)) return 0.0;
    return dist_lp(l1, l2.a);
}
Real dist_ss(const Segment& s1, const Segment& s2) {
    if(is_intersect_ss(s1, s2)) return 0.0;
    return min({dist_sp(s1, s2.a), dist_sp(s1, s2.b), dist_sp(s2, s1.a), dist_sp(s2, s1.b)});
}
Real dist_ls(const Line& l, const Segment& s) {
    if(is_intersect_ls(l, s)) return 0.0;
    return min(dist_lp(l, s.a), dist_lp(l, s.b));
}
Real dist_sl(const Segment& s, const Line& l) {
    return dist_ls(l, s);
}
Real area(const vector<Point>& polygon) {
    Real res = 0.0;
    const int n = (int)polygon.size();
    for(int i = 0; i < n; ++i) {
        res += cross(polygon[i], polygon[(i + 1) % n]);
    }
    return abs(res * 0.5);
}
bool is_convex(const vector<Point>& polygon) {
    const int n = (int)polygon.size();
    for(int i = 0; i < n; ++i) {
        if(ccw(polygon[(i - 1 + n) % n], polygon[i], polygon[(i + 1) % n]) == -1) return false;
    }
    return true;
}
int in_polygon(const vector<Point>& polygon, const Point& p) {
    const int n = (int)polygon.size();
    int ret = 0;
    for(int i = 0; i < n; ++i) {
        Point a = polygon[i] - p, b = polygon[(i + 1) % n] - p;
        if(eq(cross(a, b), 0.0) and sign(dot(a, b)) <= 0) return 1;
        if(a.imag() > b.imag()) swap(a, b);
        if(sign(a.imag()) <= 0 and sign(b.imag()) == 1 and sign(cross(a, b)) == 1) ret ^= 2;
    }
    return ret;
}
vector<Point> convex_hull(vector<Point> ps) {
    sort(ps.begin(), ps.end(), comp_x);
    ps.erase(unique(ps.begin(), ps.end()), ps.end());
    int n = (int)ps.size(), k = 0;
    if(n == 1) return ps;
    vector<Point> ch(2 * n);
    for(int i = 0; i < n; ch[k++] = ps[i++]) {
        while(k >= 2 and sign(cross(ch[k - 1] - ch[k - 2], ps[i] - ch[k - 1])) == -1) {
            --k;
        }
    }
    for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--]) {
        while(k >= t and sign(cross(ch[k - 1] - ch[k - 2], ps[i] - ch[k - 1])) == -1) {
            --k;
        }
    }
    ch.resize(k - 1);
    return ch;
}
Real convex_diameter(const vector<Point>& polygon) {
    int n = (int)polygon.size(), is = 0, js = 0;
    for(int i = 1; i < n; ++i) {
        if(sign(polygon[i].imag() - polygon[is].imag()) == 1) is = i;
        if(sign(polygon[i].imag() - polygon[js].imag()) == -1) js = i;
    }
    Real maxdis = norm(polygon[is] - polygon[js]);
    int i = is, j = js;
    do {
        if(sign(cross(polygon[(i + 1) % n] - polygon[i], polygon[(j + 1) % n] - polygon[j])) >= 0) {
            j = (j + 1) % n;
        } else {
            i = (i + 1) % n;
        }
        if(norm(polygon[i] - polygon[j]) > maxdis) {
            maxdis = norm(polygon[i] - polygon[j]);
        }
    } while(i != is or j != js);
    return sqrt(maxdis);
}
vector<Point> convex_cut(const vector<Point>& polygon, const Line& l) {
    const int n = (int)polygon.size();
    vector<Point> res;
    for(int i = 0; i < n; ++i) {
        const Point cur = polygon[i], nex = polygon[(i + 1) % n];
        if(ccw(l.a, l.b, cur) != -1) res.emplace_back(cur);
        if(ccw(l.a, l.b, cur) * ccw(l.a, l.b, nex) < 0) {
            res.emplace_back(intersection_ll(Line(cur, nex), l)[0]);
        }
    }
    return res;
}
int main(void) {
    while(1) {
        int n, kp, kq, kr;
        cin >> n >> kp >> kq >> kr;
        kp--;
        kq--;
        kr--;
        if(n == 0) break;
        vector<Point> poly(n);
        rep(i, 0, n) {
            cin >> poly[i];
        }
        vector<Real> tp, tq, tr, t;
        tp.push_back(0.0l);
        tq.push_back(0.0l);
        tr.push_back(0.0l);
        t.push_back(0.0l);
        rep(i, 0, n) {
            Real dp = abs(poly[(kp + i + 1) % n] - poly[(kp + i) % n]);
            tp.push_back(tp.back() + dp);
            Real dq = abs(poly[(kq + i + 1) % n] - poly[(kq + i) % n]);
            tq.push_back(tq.back() + dq);
            Real dr = abs(poly[(kr + i + 1) % n] - poly[(kr + i) % n]);
            tr.push_back(tr.back() + dr);
            t.push_back(tp.back());
            t.push_back(tq.back());
            t.push_back(tr.back());
        }
        sort(t.begin(), t.end());
        t.erase(unique(t.begin(), t.end()), t.end());
        // rep(i, 0, (int)t.size()) {
        //     cout << i << ' ' << t[i] << '\n';
        // }
        // cout << '\n';
        Real ans = inf;
        rep(i, 0, (int)t.size() - 1) {
            // cout << i << "\n\n";
            int ip = upper_bound(tp.begin(), tp.end(), t[i]) - tp.begin() - 1;
            int iq = upper_bound(tq.begin(), tq.end(), t[i]) - tq.begin() - 1;
            int ir = upper_bound(tr.begin(), tr.end(), t[i]) - tr.begin() - 1;
            // cout << ip << ' ' << iq << ' ' << ir << "\n\n";
            Point dirp = (poly[(kp + ip + 1) % n] - poly[(kp + ip) % n]) / abs(poly[(kp + ip + 1) % n] - poly[(kp + ip) % n]);
            Point dirq = (poly[(kq + iq + 1) % n] - poly[(kq + iq) % n]) / abs(poly[(kq + iq + 1) % n] - poly[(kq + iq) % n]);
            Point dirr = (poly[(kr + ir + 1) % n] - poly[(kr + ir) % n]) / abs(poly[(kr + ir + 1) % n] - poly[(kr + ir) % n]);
            Point sp = poly[(kp + ip) % n] + dirp * (t[i] - tp[ip]);
            Point sq = poly[(kq + iq) % n] + dirq * (t[i] - tq[iq]);
            Point sr = poly[(kr + ir) % n] + dirr * (t[i] - tr[ir]);
            Point gp = poly[(kp + ip) % n] + dirp * (t[i + 1] - tp[ip]);
            Point gq = poly[(kq + iq) % n] + dirq * (t[i + 1] - tq[iq]);
            Point gr = poly[(kr + ir) % n] + dirr * (t[i + 1] - tr[ir]);
            assert(eq(abs(gp - sp), t[i + 1] - t[i]));
            assert(eq(abs(gq - sq), t[i + 1] - t[i]));
            assert(eq(abs(gr - sr), t[i + 1] - t[i]));
            // cout << sp << ' ' << gp << '\n';
            // cout << sq << ' ' << gq << '\n';
            // cout << sr << ' ' << gr << '\n';
            // cout << '\n';
            Real a1x = gp.real() - sp.real(), b1x = sp.real();
            Real a1y = gp.imag() - sp.imag(), b1y = sp.imag();
            Real a2x = gq.real() - sq.real(), b2x = sq.real();
            Real a2y = gq.imag() - sq.imag(), b2y = sq.imag();
            Real a3x = gr.real() - sr.real(), b3x = sr.real();
            Real a3y = gr.imag() - sr.imag(), b3y = sr.imag();
            Real a = (a2x - a1x) * (a3y - a1y) - (a2y - a1y) * (a3x - a1x);
            Real b = (a2x - a1x) * (b3y - b1y) + (b2x - b1x) * (a3y - a1y) - (a2y - a1y) * (b3x - b1x) - (b2y - b1y) * (a3x - a1x);
            Real c = (b2x - b1x) * (b3y - b1y) - (b2y - b1y) * (b3x - b1x);
            // cout << a << ' ' << b << ' ' << c << '\n';
            // cout << '\n';
            ans = min(ans, abs(c) / 2.0l);
            ans = min(ans, abs(a + b + c) / 2.0l);
            if(eq(a, 0.0l)) {
                if(!eq(b, 0.0l)) {
                    Real cand = -c / b;
                    if(0.0l <= cand and cand <= 1.0l) {
                        ans = min(ans, 0.0l);
                    }
                }
            } else {
                Real cand1 = -b / (2.0l * a);
                if(0.0l <= cand1 and cand1 <= 1.0l) {
                    ans = min(ans, abs(a * cand1 * cand1 + b * cand1 + c) / 2.0l);
                }
                if(b * b - 4.0l * a * c >= 0) {
                    Real cand2 = (-b - sqrtl(b * b - 4.0l * a * c)) / (2.0l * a);
                    if(0.0l <= cand2 and cand2 <= 1.0l) {
                        ans = min(ans, 0.0l);
                    }
                    Real cand3 = (-b + sqrtl(b * b - 4.0l * a * c)) / (2.0l * a);
                    if(0.0l <= cand3 and cand3 <= 1.0l) {
                        ans = min(ans, 0.0l);
                    }
                }
            }
        }
        cout << ans << '\n';
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3716
final_rank: 7