/*
#include<iostream>
#include<cstdio>
#include<cmath>
#include<sstream>
#include<algorithm>
#include<cassert>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<28)
#define F first
#define S second
#define all(n) (n).begin(),(n).end()
#define EPS (1e-8)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)
using namespace std;
typedef pair<int,int> ii;
typedef vector<int> vi;
typedef vector<vi> vvi;
struct Point
{
  double x,y;
  int index;
  Point(double x=-inf,double y=-inf):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 p){return Point(x*p,y*p);}
 
  bool operator < (const Point& p)const
  {
    return !equals(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;
  }
};
 
struct Segment
{
  Point p1,p2;
  Segment(Point p1=Point(-inf,-inf),Point p2=Point(-inf,-inf)):p1(p1),p2(p2){}
};
 
typedef vector<Point> Polygon;
typedef Segment Line;
typedef vector<Point> Polygon;
 
double dot(Point a,Point b)
{
  return a.x*b.x+a.y*b.y;
}
 
double cross(Point a,Point b)
{
  return a.x*b.y-a.y*b.x;
}
 
double norm(Point a)
{
  return a.x*a.x+a.y*a.y;
}
 
double toRad(double agl)
{
  return agl*M_PI/180.0;
}
 
int ccw(Point p0,Point p1,Point p2)
{
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) <-EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS) return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}
 
 
bool PointEquals(Point a,Point b)
{
  return equals(a.x,b.x) && equals(a.y,b.y);
}
 
double abs(Point a)
{
  return sqrt(norm(a));
}
 
double getDistanceLP(Line s,Point p)
{
  return abs(cross(s.p2-s.p1,p-s.p1))/abs(s.p2-s.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);
}
 
Polygon andrewScan(Polygon s,Point now)
{
  Polygon u,l;
  if(s.size() < 3)return s;
  sort(all(s));
 
  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size()-1]);
  l.push_back(s[s.size()-2]);
 
  REP(i,2,s.size())
    {
      for(int n=u.size();n>=2 && ccw(u[n-2],u[n-1],s[i]) != 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 && ccw(l[n-2],l[n-1],s[i]) != 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]);
  reverse(l.begin(),l.end());
 

  vector<Point> ret;
 
  bool f = false;
  rep(i,l.size())
    {
      if(l[i].index == now.index)f = true;
      if(f == false)continue;
      ret.push_back(l[i]);
      rep(j,s.size())
    {
      if(s[j].index == l[i].index || s[j].index == l[(i+1)%l.size()].index)continue;
      if(getDistanceSP(Segment(l[i],l[(i+1)%l.size()]),s[j]) == ON_SEGMENT)ret.push_back(s[j]);
    }
    }
 
  rep(i,l.size())
    {
      if(l[i].index == now.index)f = false;
      if(f == false)break;
      ret.push_back(l[i]);
 
      rep(j,s.size())
    {
      if(s[j].index == l[i].index || s[j].index == l[(i+1)%l.size()].index)continue;
      if(getDistanceSP(Segment(l[i],l[(i+1)%l.size()]),s[j]) == ON_SEGMENT)ret.push_back(s[j]);
    }
 
    }
 
 
  return ret;
}

vector<Point> convex_hull(vector<Point> ps) {
  int n = ps.size(), k = 0;
  sort(ps.begin(), ps.end());
  vector<Point> ch(2*n);
  for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
    while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
  for (int i = n-2, t = k+1; i >= 0; ch[k++] = ps[i--]) // upper-hull
    while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
  ch.resize(k-1);
  return ch;
} 

 
int n;
vector<Point> input;
 
void inputt()
{
  input.clear();
  input.resize(n);
  rep(i,n)
    {
      cin >> input[i].x >> input[i].y;
      input[i].index = i; 
    }
}
  
void solve()
{
  bool used[n];
  rep(i,n)used[i] = false;
  double L = 0;
  Point cur = Point(0,0); 
  cur.index = -1; 

  rep(_,n)
    {
      vector<Point> toConvex;
      rep(i,n)
	{
	  if(used[i])continue;
	  toConvex.push_back(input[i]);
	}
      toConvex.push_back(cur);

      toConvex = convex_hull(toConvex);
      reverse(toConvex.begin(),toConvex.end());

      vector<Point> tmp;
      rep(j,toConvex.size())
	{
	  tmp.push_back(toConvex[j]);
	  rep(i,n)
	    {
	      if(used[i])continue;
	      if(toConvex[j].index == input[i].index || toConvex[(j+1)%toConvex.size()].index == input[i].index)continue;
	      if(equals(getDistanceSP(Segment(toConvex[j],toConvex[(j+1)%toConvex.size()]),input[i]),0))
		{
		  tmp.push_back(input[i]);
		}
	    }
	}
      toConvex = tmp;

      
      cout << "toConvex----- cur : " << cur.x << "," << cur.y << endl;
      rep(i,toConvex.size())
      {
	  cout << toConvex[i].x << "," << toConvex[i].y  << " " << toConvex[i].index<< endl;
	}
      cout << endl;
      

      int next = -inf;
      rep(i,toConvex.size())
	{
	  if(toConvex[i].index == cur.index)
	    {
	      next = toConvex[(i+1)%toConvex.size()].index;
	      break;
	    }
	}
      
      assert(next != -inf);
      cout << "next = " << next << " : " << input[next].x << "," << input[next].y << endl;
      used[next] = true;
      L += sqrt(norm(cur-input[next]));
      cur = input[next];

    }

  L *= 10.0;
  L = round(L);
  L /= 10.0;
  cout << setiosflags(ios::fixed) << setprecision(1) << L << endl;
}
 
int main()
{
  while(cin >> n,n)
    {
      inputt();

      solve();
 
    }
  return 0;
}

//テ・ツ、ツ嘉ヲツ閉ーテ」ツ?ォテ、ツクツ?ヲツ猟ヲテ」ツ??」ツつ古」ツ?ヲテ」ツ?淌」ツつ嘉」ツ?ーテ」ツ?静」ツ?」テ」ツ??

*/

#include<cstdio>
#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
#include<cassert>
#include<iomanip>
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<28)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define all(n) (n).begin(),(n).end()
#define pow2(a) (a)*(a)
using namespace std;
double EPS = 1e-9;

bool equals(double a,double b)
{
  return fabs((a)-(b)) < EPS;
}

class Point
{
  public:
  int x,y;

  Point(int x = -1,int y = -1): 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 * (int a){return Point(a*x,a*y);}
  Point operator / (int a){return Point(x/a,y/a);}

  bool operator < (const Point& p) const
  {
    return x != p.x?x<p.x:y<p.y;
  }

};

struct Segment
{
  Point p1,p2;
  Segment(Point p1 = Point(-1,-1),Point p2 = Point(-1,-1)):p1(p1),p2(p2){}
};
typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;


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

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

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

double getArgV2(Point A,Point B)
{
  return acos(dot(A,B)/(sqrt(norm(A))*sqrt(norm(B))));
  double a = sqrt(norm(A));
  double b = sqrt(norm(B));
  return acos(dot(A,B)/(a*b));
}

bool cmp(const Point &a,const Point &b)
{
  if(a.x != b.x)return a.x < b.x;
  return a.y < b.y;
}

Point ps[1000];
bool used[1000];

int main()
{
 
  int n;
  while(cin >> n,n)
    {
      rep(i,n)cin >> ps[i].x >> ps[i].y;
      Point cur(0,0);
      Point cur2(0,-500);
      double L = 0;
      int last = n;

      rep(_,n)
	{
	  /*
	  cout << "remain"<<endl;
	  rep(i,last)
	    {
	      cout << ps[i].x << "," << ps[i].y << endl;
	    }
	  cout << endl;
	  */
	  int next = 0;
	  REP(i,1,last)
	    {
	      if(equals(atan2(ps[next].y-cur.y,ps[next].x-cur.x),atan2(ps[i].y-cur.y,ps[i].x-cur.x)))
	      //if(equals(getArgV2(cur-cur2,ps[next]-cur), getArgV2(cur-cur2,ps[i]-cur)))
		{
		  if(pow2(cur.x-ps[next].x)+pow2(cur.y-ps[next].y) > pow2(cur.x-ps[i].x)+pow2(cur.y-ps[i].y))
		    {
		      next = i;
		    }
		}
	      else if(getArgV2(cur-cur2,ps[next]-cur) > getArgV2(cur-cur2,ps[i]-cur))
		{
		  next = i;
		}
	    }
	  //cout << "erase : " << ps[next].x << "," << ps[next].y << endl;
	  L += sqrt(pow2(cur.x-ps[next].x)+pow2(cur.y-ps[next].y));
	  cur2 = cur;
	  cur = ps[next];
	  ps[next] = ps[last-1];
	  last--;
	}
      
      L *= 10;
      L = round(L);
      L /= 10.0;
      cout << setiosflags(ios::fixed) << setprecision(1) << L << endl;
      //printf("%.1f\n",L);
    }
  return 0;
}


/*
int main()
{
  Point A = Point(0,10);
  Point B = Point(-10,15);

  cout << atan2(B.y-A.y,B.x-A.x)*180/M_PI << endl;
  B = Point(11,20);
  cout << atan2(B.y-A.y,B.x-A.x)*180/M_PI << endl;


  int n; 
  while(cin >> n,n)
    {
   

      Point cur1 = Point(0,0);
      Point cur2 = Point(0,0);

      rep(i,n)
	{
	  cin >> ps[i].x >> ps[i].y;
	  cout << i << " :: " << ps[i].x << "," << ps[i].y << endl;
	  used[i] = false;
	}
      cout << atan2(ps[5].y-ps[4].y,ps[5].x-ps[4].x)*180/M_PI << endl;
      cout << "##### " << getArgV2(ps[5]-ps[4],ps[4]-Point(0,0))*180/M_PI << endl;
      sort(ps,ps+n,cmp);



      bool f = true;
      double L = 0;
      rep(_,n)
	{
	  if(_ == 0)
	    {
	      L += sqrt(norm(ps[0]-cur1));
	      cur1 = ps[0];
	      used[0] = true;
	      //cout << "L = " << L << endl;
	      continue;
	    }
	  double minArg = inf;
	  double minDist = inf;
	  int minpos = -inf;
	  rep(i,n)
	    {
	      if(used[i])continue;

	      //cout << "cur1(" << cur1.x << "," << cur1.y << ")" << endl;
	      //cout << "cur2(" << cur2.x << "," << cur2.y << ")" << endl;
	      //cout << "ps["<<i<<"](" << ps[i].x << "," << ps[i].y << ")" << endl;

	      double arg = getArgV2(cur1-cur2,ps[i]-cur1);

	      if(f)
		{
		  f = false;
		  minpos = i;
		  minArg = arg;
		  continue;
		}

	      //cout << arg << " ::: " << endl;
	      if(!equals(arg,minArg) && arg < minArg)
		{
		  minpos = i;
		  minArg = arg;
		  minDist = sqrt(norm(cur1-ps[i]));
		}
	      if(equals(arg,minArg) && sqrt(norm(cur1-ps[minpos])) > sqrt(norm(cur1-ps[i])))
		{
		  minDist = sqrt(norm(cur1-ps[i]));
		  minpos = i;
		
		}

	    }
	  //cout << "cur1 (" << cur1.x << "," << cur1.y << ")" << endl;
	  //cout << "phase #" << _ << " " << minpos << "(" << ps[minpos].x << "," << ps[minpos].y << ")" << endl;
	  //cout << "that arg is " << minArg*180/M_PI << endl;

	  //assert(minpos != -inf);
	  used[minpos] = true;
	  L += sqrt(norm(cur1-ps[minpos]));
	  cur2 = cur1;
	  cur1 = ps[minpos];

	  //cout << "L = " << L << endl << endl;
	}
      //L *= 10.0;
      //L = round(L);
      //L /= 10.0;
      //cout << setiosflags(ios::fixed) << setprecision(1) << L << endl;
      printf("%.1f\n",L);
    }
  return 0;
}
*/
/*
#include<cstdio>
#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
#include<cassert>
#include<iomanip>
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<28)
#define all(n) (n).begin(),(n).end()

using namespace std;
double EPS = 1e-9;

bool equals(double a,double b)
{
  return fabs((a)-(b)) < EPS;
}

struct Point
{
  double x,y;
  Point(double x=-inf,double y=-inf):x(x),y(y){}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  bool operator < (const Point &b)const
  {
    if(x != b.x)return x < b.x;
    return y < b.y;
  }
};

Point ps[410];
bool use[410];

double toRad(double agl){ return agl*M_PI/180; }

double getArg(Point a,Point bb)
{

}

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

int main()
{
  int n;
  while(cin >> n,n)
    {
      rep(i,n)
	{
	  cin >> ps[i].x >> ps[i].y;
	  use[i] = false;
	}
      sort(ps,ps+n);

      Point cur = Point(0,0);
      Point cur2 = Point(0,0);
      double L = 0;
      rep(_,n)
	{
	  if(!_)
	    {
	      cur = ps[0];
	      use[0] = true;
	      L += sqrt(norm(cur-ps[0]));
	      continue;
	    }
	  cout << "cur " << cur.x << "," << cur.y << endl;
	  cout << "cur2 " << cur2.x << "," << cur2.y << endl;
	  int next = -inf;
	  double maxArg = -inf;

	  rep(i,n)
	    {
	      if(use[i])continue;
	      //cout << "i = "<< i << endl;

	      Point cc = cur - cur2;
	      double arg = atan2(ps[i].y-cc.y,ps[i].x-cc.x);

	      if(!equals(arg,toRad(90)) && arg > toRad(90))arg = toRad(-180)-(toRad(180)-arg);
	      cout << i << " arg = " << arg*180/M_PI << " max : " << maxArg << endl;
	      if(!equals(arg,maxArg) && arg > maxArg)
		{
		  maxArg = arg;
		  next = i;
		}
	      else if(equals(arg,maxArg) &&  norm(ps[next]-cur) > norm(ps[i]-cur) )
		{
		  next = i;
		}
	      //cout << endl;
	    }
	  cout << "next = " << next << " " << ps[next].x << "," << ps[next].y << endl;
	  assert(next != -inf);
	  L += sqrt(pow(cur.x-ps[next].x,2)+pow(cur.y-ps[next].y,2));
	

	  cur2 = cur;
	  cur = ps[next];
	  use[next] = true;
	  cout << endl << endl;
	}

      printf("%.1f\n",L);
    }
  return 0;
}





*/

Measured memory_bytes: 1376