#include <cstdio>
#include <complex>
#include <queue>
#include <cmath>
#include <vector>
#include <cassert>
#include <cstring>
#include <algorithm>
using namespace std;

#define EPS 1e-8

typedef complex<double> P;

struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
};

double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}

double dist(const P& a, const P& b)
{
	return sqrt((a.real()-b.real())*(a.real()-b.real())+(a.imag()-b.imag())*(a.imag()-b.imag()));
}

bool intersectLL(const L &l, const L &m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || // non-parallel
         abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}

bool intersectLP(const L &l, const P &p) {
  return abs(cross(l[1]-p, l[0]-p)) < EPS;
}

bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}

P crosspoint(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]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

class Edge
{
public:
	int to,l,pt;
	double c;
	Edge(int to, int l, double c, int pt)
	:to(to), l(l), c(c), pt(pt)
	{}
};

class Trl
{
public:
	int p,l,t,h,pts;
	double c;
	Trl(int p, int l, int t, int h, double c)
	:p(p),l(l),t(t),c(c),h(h)
	{}
	
	bool operator<(const Trl& a) const
	{
		if(t!=a.t) return t>a.t;
		return c>a.c;
	}
};

typedef vector<Edge> Node;
Node node[1000];
int N;
bool v[1<<10][1000];

bool isequal(const P& a, const P& b)
{
	double rd=a.real()-b.real();
	double id=a.imag()-b.imag();
	
	return (fabs(rd) < EPS && fabs(id) < EPS);
}

void MakeGraph(vector<L>& Lines, vector<P>& pt)
{
	for(int i=0; i<1000; i++) 
		node[i].clear();
		
	bool itr[50][1000]={0};
	for(int i=0; i<pt.size(); i++)
	for(int j=0; j<Lines.size(); j++)
		if(intersectLP(Lines[j], pt[i])) itr[j][i]=1;
	
	for(int i=0; i<pt.size(); i++)
	for(int j=0; j<Lines.size(); j++)
	{
		if(!itr[j][i]) continue;
		
		for(int k=i+1; k<pt.size(); k++) //i:src j:road k:dst
		{
			if(!itr[j][k]) continue;
			
			int t=0,ts=0;
			for(int l=0; l<N; l++)
			{
				if(intersectSP(L(pt[i], pt[k]), pt[l]))
				{
					t|=(1<<l);
					ts++;
				}
			}
			if(ts<=1) continue;
			node[i].push_back(Edge(k, j, dist(pt[i], pt[k]), t));
			node[k].push_back(Edge(i, j, dist(pt[i], pt[k]), t));
		}
	}
}

void Dijkstra()
{
	memset(v,0,sizeof(v));
	priority_queue<Trl> q;
	
	for(int i=0; i<N; i++)
		q.push(Trl(i,49,-1,0,0));
		
	while(1)
	{
		Trl t=q.top(); q.pop();
		
		if(v[t.h][t.p]) continue;
		v[t.h][t.p]=1;
		
		if(t.h==(1<<N)-1)
		{
			printf("%d %.8f\n", t.t, t.c);
			return;
		}
		
		for(int i=0; i<node[t.p].size(); i++)
		{
			Edge e=node[t.p][i];
			if(e.l==t.l) continue;
			int th=t.h|e.pt;
			
			if(v[th][e.to]) continue;
			q.push(Trl(e.to, e.l, t.t+1, th, t.c+e.c));
		}
	}
}


int main()
{
	while(scanf("%d", &N), N)
	{
		vector<P> pt;
		for(int i=0; i<N; i++)
		{
			int x,y;
			scanf("%d%d", &x, &y);
			pt.push_back(P(x,y));
		}
		
		vector<L> Lines;
		bool cont[1<<10]={0};
		for(int i=0; i<N; i++)
		for(int j=i+1; j<N; j++)
		{
			int h=0;
			L l=L(pt[i], pt[j]);
			for(int k=0; k<N; k++)
				if(intersectLP(l, pt[k])) h|=(1<<k);
			
			if(cont[h]) continue;
			cont[h]=1;
			Lines.push_back(l);
		}
		
		for(int i=0; i<Lines.size(); i++)
		for(int j=i+1; j<Lines.size(); j++)
		{
			if(intersectLL(Lines[i], Lines[j]))
			{
				P x=crosspoint(Lines[i], Lines[j]);
				bool g=true;
				for(int k=0; k<pt.size(); k++)
				{
					if(isequal(pt[k], x))
					{
						g=false;
						break;
					}
				}
				
				if(g) pt.push_back(x);
			}
		}
		
		MakeGraph(Lines, pt);
		Dijkstra();
	}
}

Measured memory_bytes: 16000