Problem: Complex Paper Folding

Dr. G, an authority in paper folding and one of the directors of Intercultural Consortium on Paper Crafts, believes complexity gives figures beauty. As one of his assistants, your job is to find the way to fold a paper to obtain the most complex figure. Dr. G defines the complexity of a figure by the number of vertices. With the same number of vertices, one with longer perimeter is more complex. To simplify the problem, we consider papers with convex polygon in their shapes and folding them only once. Each paper should be folded so that one of its vertices exactly lies on top of another vertex.

Write a program that, for each given convex polygon, outputs the perimeter of the most complex polygon obtained by folding it once.

Figure 1 (left) illustrates the polygon given in the first dataset of Sample Input. This happens to be a rectangle. Folding this rectangle can yield three different polygons illustrated in the Figures 1-a to c by solid lines. For this dataset, you should answer the perimeter of the pentagon shown in Figure 1-a. Though the rectangle in Figure 1-b has longer perimeter, the number of vertices takes priority.

<image> | <image> | <image> | <image>
---|---|---|---
| (a) | (b) | (c)

Figure 1: The case of the first sample input

Figure 2 (left) illustrates the polygon given in the second dataset of Sample Input, which is a triangle. Whichever pair of its vertices are chosen, quadrangles are obtained as shown in Figures 2-a to c. Among these, you should answer the longest perimeter, which is that of the quadrangle shown in Figure 2-a.

<image> | <image> | <image> | <image>
---|---|---|---
| (a) | (b) | (c)

Figure 2: The case of the second sample input

Although we start with a convex polygon, folding it may result a concave polygon. Figure 3 (left) illustrates the polygon given in the third dataset in Sample Input. A concave hexagon shown in Figure 3 (right) can be obtained by folding it, which has the largest number of vertices.

<image> <image>
Figure 3: The case of the third sample input

Figure 4 (left) illustrates the polygon given in the fifth dataset in Sample Input. Although the perimeter of the polygon in Figure 4-b is longer than that of the polygon in Figure 4-a, because the polygon in Figure 4-b is a quadrangle, the answer should be the perimeter of the pentagon in Figure 4-a.

<image> | <image> | <image>
---|---|---
| (a) | (b)

Figure 4: The case of the fifth sample input

Input

The input consists of multiple datasets, each in the following format.

> n
>  x1 y1
>  ...
>  xn yn
>

n is the number of vertices of the given polygon. n is a positive integer satisfying 3 ≤ n ≤ 20. (xi, yi) gives the coordinates of the i-th vertex. xi and yi are integers satisfying 0 ≤ xi, yi < 1000. The vertices (x1, y1), ..., (xn, yn) are given in the counterclockwise order on the xy-plane with y axis oriented upwards. You can assume that all the given polygons are convex.

All the possible polygons obtained by folding the given polygon satisfy the following conditions.

* Distance between any two vertices is greater than or equal to 0.00001.
* For any three consecutive vertices P, Q, and R, the distance between the point Q and the line passing through the points P and R is greater than or equal to 0.00001.



The end of the input is indicated by a line with a zero.

Output

For each dataset, output the perimeter of the most complex polygon obtained through folding the given polygon. The output value should not have an error greater than 0.00001. Any extra characters should not appear in the output.

Sample Input


4
0 0
10 0
10 5
0 5
3
5 0
17 3
7 10
4
0 5
5 0
10 0
7 8
4
0 0
40 0
50 5
0 5
4
0 0
10 0
20 5
10 5
7
4 0
20 0
24 1
22 10
2 10
0 6
0 4
18
728 997
117 996
14 988
1 908
0 428
2 98
6 54
30 28
106 2
746 1
979 17
997 25
998 185
999 573
999 938
995 973
970 993
910 995
6
0 40
0 30
10 0
20 0
40 70
30 70
0


Output for the Sample Input


23.090170
28.528295
23.553450
97.135255
34.270510
57.124116
3327.900180
142.111776






Example

Input

4
0 0
10 0
10 5
0 5
3
5 0
17 3
7 10
4
0 5
5 0
10 0
7 8
4
0 0
40 0
50 5
0 5
4
0 0
10 0
20 5
10 5
7
4 0
20 0
24 1
22 10
2 10
0 6
0 4
18
728 997
117 996
14 988
1 908
0 428
2 98
6 54
30 28
106 2
746 1
979 17
997 25
998 185
999 573
999 938
995 973
970 993
910 995
6
0 40
0 30
10 0
20 0
40 70
30 70
0


Output

23.090170
28.528295
23.553450
97.135255
34.270510
57.124116
3327.900180
142.111776

Solution (in CPP):

Solution:
#include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
using namespace std;

const double EPS = 1e-5;
const double INF = 1e12;
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};

namespace std{
    bool operator < (const P& a, const P& b){
        return (a.X!=b.X) ? a.X<b.X : a.Y<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(abs(c)-abs(b) > EPS) return -2; //a-b-c
    return 0; //a-c-b
}

bool intersectSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) <= 0 ) &&
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) <= 0 );
}
bool intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS  && dot(s[0]-p, s[1]-p)<EPS;
}

P projection(const L& l, const P& p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}
P reflection(const L& l, const P& p) {
  return p + 2.0*(projection(l, p) -p);
}

double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}
P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1]-l[0], m[1]-m[0]);
  double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B/A *(m[1]-m[0]);
}

bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}

int in_poly(const P &p, const VP &poly){
    int n = poly.size();
    int ret = -1;
    for(int i=0; i<n; i++){
        P a = poly[i]-p;
        P b = poly[(i+1)%n]-p;
        if(a.Y > b.Y) swap(a,b);
        if(intersectSP(L(a,b), P(0,0))) return 0;
        if(a.Y<=0 && b.Y>0 && cross(a,b)<0) ret = 1-ret;
    }
    return ret;
}
double getarea(const VP &poly){
    double ret = 0;
    for (int i=0; i<(int)poly.size(); i++){ 
        ret += cross(poly[i], poly[(i+1)%poly.size()]);
    }
    return ret*0.5;
}

VP convex(VP v){
    VP ret;
    int n = v.size();
    sort(v.begin(), v.end());
    for(int i=0; i<n; i++){
        while((int)ret.size()>1 && cross(ret.back()-ret[ret.size()-2], v[i]-ret.back()) < EPS){
            ret.pop_back();
        }
        ret.push_back(v[i]);
    }
    int t = ret.size();
    for(int i=n-2; i>=0; i--){
        while((int)ret.size()>t && cross(ret.back()-ret[ret.size()-2], v[i]-ret.back()) < EPS){
            ret.pop_back();
        }
        ret.push_back(v[i]);
    }
    if((int)ret.size() > 1) ret.pop_back();
    return ret;
}

VP convex_cut(const VP& p, const L& l){
    VP ret;
    int n = p.size();
    for(int i=0; i<n; i++){
        P curr = p[i];
        P next = p[(i+1)%n];
        if(ccw(l[0], l[1], curr) != -1) ret.push_back(curr);
        if(ccw(l[0], l[1], curr) *ccw(l[0], l[1], next) == -1){
            ret.push_back(crosspointLL(L(curr, next), l));
        }
    }
    return ret;
}

vector<L> arrangement(const vector<L> &e){
    vector<VP> cp(e.size());
    for(int i=0; i<(int)e.size(); i++){
        for(int j=i+1; j<(int)e.size(); j++){
            if(!isParallel(e[i], e[j]) && intersectSS(e[i], e[j])){
                P cpij = crosspointLL(e[i], e[j]);
                cp[i].push_back(cpij);
                cp[j].push_back(cpij);
            }
        }
        sort(cp[i].begin(), cp[i].end());
        cp[i].erase(unique(cp[i].begin(), cp[i].end()), cp[i].end());
    }

    vector<L> ret;
    for(int i=0; i<(int)e.size(); i++){
        for(int j=0; j<(int)cp[i].size()-1; j++){
            ret.push_back(L(cp[i][j], cp[i][j+1]));
        }
    }
    
    for(int i=ret.size()-1; i>=0; i--){
        for(int j=0; j<i; j++){
            if(ret[i] == ret[j]) ret.erase(ret.begin() +i);
        }
    }
    return ret;
}

VP convex_union(VP c1, VP c2){
    int n = c1.size(), m = c2.size();
    
    vector<L> edges;
    for(int r=0; r<2; r++){
        for(int i=0; i<n; i++){
            edges.push_back(L(c1[i], c1[(i+1)%n]));
        }
        swap(c1, c2);
        swap(n, m);
    }
    vector<L> arr = arrangement(edges);

    vector<L> elist;
    for(int i=0; i<(int)arr.size(); i++){
        P mid = (arr[i][0] + arr[i][1]) /2.0;
        if(in_poly(mid, c1) <= 0 && in_poly(mid, c2) <= 0){
            elist.push_back(arr[i]);
        }
    }

    VP res;
    res.push_back(elist[0][0]);
    res.push_back(elist[0][1]);
    elist.erase(elist.begin());
    while(!elist.empty()){
        bool erased = false; //バグの一時しのぎ
        for(int i=0; i<(int)elist.size(); i++){
            if(res.back() == elist[i][0] || res.back() == elist[i][1]){
                if(res.back() == elist[i][1]) swap(elist[i][0], elist[i][1]);
                res.push_back(elist[i][1]);
                elist.erase(elist.begin() +i);
                erased = true;
            }
        }
        //エラーで無限ループするので要修正
        if(!erased){
            return VP();
        }
    }

    for(int i=res.size()-1; i>=0; i--){
        P prev = res[(i+res.size()-1)%res.size()];
        P next = res[(i+1)%res.size()];
        if(distanceLP(L(prev, next), res[i]) < EPS){
            res.erase(res.begin() +i);
        }
    }

    if(getarea(res) < 0) reverse(res.begin(), res.end());
    return res;
}

pair<int, double> solve(int s, int t, VP poly){
    P p1 = (poly[s] +poly[t])/2.0 +(poly[s] -poly[t])*P(0,1);
    P p2 = (poly[s] +poly[t])/2.0 -(poly[s] -poly[t])*P(0,1);
    VP c1 = convex_cut(poly, L(p1, p2));
    VP c2 = convex_cut(poly, L(p2, p1));
    for(int i=0; i<(int)c2.size(); i++){
        c2[i] = reflection(L(p1, p2), c2[i]);
    }
    reverse(c2.begin(), c2.end());
    VP res = convex_union(c1, c2);
    
    double len = 0;
    for(int i=0; i<(int)res.size(); i++){
        len += abs(res[i] -res[(i+1)%res.size()]);
    }
    return make_pair((int)res.size(), len);
}

int main(){
    cout << fixed;
    cout << setprecision(10);
    while(1){
        int n;
        cin >> n;
        if(n==0) break;

        VP poly(n);
        for(int i=0; i<n; i++){
            int x,y;
            cin >> x >> y;
            poly[i] = P(x, y);
        }

        double ans = 0;
        int cmax = 0;
        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                pair<int, double> ret = solve(i, j, poly);
                if(ret.first == cmax){
                    ans = max(ans, ret.second);
                }else if(ret.first > cmax){
                    cmax = ret.first;
                    ans = ret.second;
                }
            }
        }
        cout << ans << endl;
    }
    return 0;
}