import java.util.*;
import java.io.*;

public class nightwatch_as implements Runnable {
    class Point {
        int x;
        int y;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public boolean equals(Object o) {
            Point point = (Point) o;
            if (x != point.x) return false;
            if (y != point.y) return false;
            return true;
        }

        public int hashCode() {
            int result;
            result = x;
            result = 31 * result + y;
            return result;
        }

        @Override
        public String toString() {
            return "(" + (x / 2) + "," + (y / 2) + ")";
        }
    }

    class Rect {
        int x1;
        int y1;
        int x2;
        int y2;

        @Override
        public String toString() {
            return "(" + (x1 / 2) + "," + (y1 / 2) + ")-(" + (x2 / 2) + "," + (y2 / 2) + ")";
        }

        boolean isInside(Point p) {
            return x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2;
        }
    }

    final double EPS = 1e-7;

    boolean between(double x, double y, double z) {
        if (Math.abs(x - z) < EPS) {
            return true;
        }
        return x + EPS < y && y < z - EPS || z + EPS < y && y < x - EPS;
    }

    boolean betweeni(double x, double y, double z) {
        return x - EPS < y && y < z + EPS || z - EPS < y && y < x + EPS;
    }

    boolean intersect(Point p1, Point p2, Point p3, Point p4) {
        long a1 = p2.y - p1.y;
        long b1 = p1.x - p2.x;
        long c1 = p1.x * a1 + p1.y * b1;
        long a2 = p4.y - p3.y;
        long b2 = p3.x - p4.x;
        long c2 = p3.x * a2 + p3.y * b2;

        long d = a1 * b2 - a2 * b1;
        if (d == 0) {
            return false;
        }
        double x = 1.0 * (c1 * b2 - c2 * b1) / d;
        double y = 1.0 * (a1 * c2 - a2 * c1) / d;
        if (!(between(p1.x, x, p2.x) && between(p1.y, y, p2.y))) {
            return false;
        }
        if (!(betweeni(p3.x, x, p4.x) && betweeni(p3.y, y, p4.y))) {
            return false;
        }
        return true;
    }

    long vp(long x1, long y1, long x2, long y2) {
        return x1 * y2 - x2 * y1;
    }

    double sp(double x1, double y1, double x2, double y2) {
        return x1 * x2 + y1 * y2;
    }

    boolean inside(int x, int y, Point[] p) {
        int n = p.length;
        double ang = 0;
        for (int i = 0; i < n; i++) {
            long vp = vp(p[i].x - x, p[i].y - y, p[(i + 1) % n].x - x, p[(i + 1) % n].y - y);
            if (betweeni(p[i].x, x, p[(i + 1) % n].x) && betweeni(p[i].y, y, p[(i + 1) % n].y) && vp == 0) {
                return true;
            }
        }
        for (int i = 0; i < n; i++) {
            ang += Math.atan2(
                    vp(p[i].x - x, p[i].y - y, p[(i + 1) % n].x - x, p[(i + 1) % n].y - y),
                    sp(p[i].x - x, p[i].y - y, p[(i + 1) % n].x - x, p[(i + 1) % n].y - y)
                    );
        }

        return Math.abs(ang) > Math.PI;
    }

    public void solve() throws IOException {
        Scanner in = new Scanner(new File("nightwatch.in"));
        PrintWriter out = new PrintWriter("nightwatch.out");

        int n = in.nextInt();
        Point[] p = new Point[n];
        for (int i = 0; i < n; i++) {
            p[i] = new Point(in.nextInt() * 2, in.nextInt() * 2);
        }
        int imin = 0;
        for (int i = 1; i < n; i++) {
            if (p[i].y < p[imin].y || (p[i].y == p[imin].y && p[i].x < p[imin].x)) {
                imin = i;
            }
        }               

        Point[] pp = p;
        p = new Point[n];
        int ind = 0;
        for (int i = imin; i < n; i++) {
            p[ind++] = pp[i];
        }
        for (int i = 0; i < imin; i++) {
            p[ind++] = pp[i];
        }

        int imax = 0;
        for (int i = 1; i < n; i++) {
            if (p[i].y > p[imax].y || (p[i].y == p[imax].y && p[i].x > p[imax].x)) {
                imax = i;
            }
        }

        int ytop = Integer.MIN_VALUE;
        int ybot = Integer.MAX_VALUE;
        for (int i = 1; i < n; i++) {
            if (p[i].x > p[i - 1].x) {
                if (p[i].y > ytop) {
                    ytop = p[i].y;
                }
            }
            if (p[i].x < p[i - 1].x) {
                if (p[i].y < ybot) {
                    ybot = p[i].y;
                }
            }
        }

        Rect tk = new Rect();
        tk.y1 = ytop;
        tk.y2 = p[imax].y;
        tk.x1 = Integer.MIN_VALUE;
        tk.x2 = Integer.MAX_VALUE;
        for (int i = 0; i < n; i++) {
            if (p[i].y > ytop && p[i].y == p[(i - 1 + n) % n].y) {
                if (p[i].y < tk.y2) {
                    tk.y2 = p[i].y;
                }
            }
            if (p[i].y > ytop && p[i].y > p[(i - 1 + n) % n].y) {
                if (p[i].x < tk.x2) {
                    tk.x2 = p[i].x;
                }
            }
            if (p[i].y > ytop && p[i].y > p[(i + 1) % n].y) {
                if (p[i].x > tk.x1) {
                    tk.x1 = p[i].x;
                }
            }
        }
        System.out.println("Top kernel: " + tk);

        Rect bk = new Rect();
        bk.y1 = p[0].y;
        bk.y2 = ybot;
        bk.x1 = Integer.MIN_VALUE;
        bk.x2 = Integer.MAX_VALUE;
        for (int i = 0; i < n; i++) {
            if (p[i].y < ybot && p[i].y == p[(i - 1 + n) % n].y) {
                if (p[i].y > bk.y1) {
                    bk.y1 = p[i].y;
                }
            }
            if (p[i].y < ybot && p[i].y < p[(i - 1 + n) % n].y) {
                if (p[i].x > bk.x1) {
                    bk.x1 = p[i].x;
                }
            }
            if (p[i].y < ybot && p[i].y < p[(i + 1) % n].y) {
                if (p[i].x < bk.x2) {
                    bk.x2 = p[i].x;
                }
            }
        }
        System.out.println("Bottom kernel: " + bk);

        Set<Point> vs = new HashSet<Point>();
        vs.addAll(Arrays.asList(p));
        for (Rect r : new Rect[]{bk, tk}) {
            for (int i = 0; i < n; i++) {
                if (r.x1 <= p[i].x && p[i].x <= r.x2) {
                    vs.add(new Point(p[i].x, r.y1));
                    vs.add(new Point(p[i].x, r.y2));
                }
                if (r.y1 <= p[i].y && p[i].y <= r.y2) {
                    vs.add(new Point(r.x1, p[i].y));
                    vs.add(new Point(r.x2, p[i].y));
                }
            }
        }

        Point[] v = vs.toArray(new Point[vs.size()]);
        int m = v.length;
        int[] type = new int[m];
        for (int i = 0; i < m; i++) {
            if (tk.isInside(v[i])) {
                type[i] |= 1;
            }
            if (bk.isInside(v[i])) {
                type[i] |= 2;
            }
        }

        double[][] a = new double[m][m];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) {
                for (int k = 0; k < n; k++) {
                    if (intersect(v[i], v[j], p[k], p[(k + 1) % n])) {
                        a[i][j] = Double.POSITIVE_INFINITY;
                        break;
                    }
                }
                if (a[i][j] == 0) {
                    if (!inside((v[i].x + v[j].x) / 2, (v[i].y + v[j].y) / 2, p)) {
                        a[i][j] = Double.POSITIVE_INFINITY;
                    } else {
                        a[i][j] = Math.hypot(v[i].x - v[j].x, v[i].y - v[j].y);
                    }
                }
            }
        }

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) {
                for (int k = 0; k < m; k++) {
                    if (a[j][k] > a[j][i] + a[i][k]) {
                        a[j][k] = a[j][i] + a[i][k];
                    }
                }
            }
        }

        double ans = Double.POSITIVE_INFINITY;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) {
                if ((type[i] & 1) != 0 && (type[j] & 2) != 0 && a[i][j] < ans) {
                    ans = a[i][j];
                }
            }
        }

        out.printf("%.10f\n", ans);
        
        in.close();
        out.close();
    }

    public void run() {
        try {
            solve();
        } catch (IOException e) {
        }
    }

    public static void main(String[] arg) {
        Locale.setDefault(Locale.US);
        new Thread(new nightwatch_as()).start();
    }
}