Problem:
Problem J:
Zigzag
Given several points on a plane, let’s try to solve a puzzle connecting them with a zigzag line.
The puzzle is to find the zigzag line that passes through all the given points with the minimum
number of turns. Moreover, when there are several zigzag lines with the minimum number of
turns, the shortest one among them should be found.
For example, consider nine points given in Figure 1.
Figure 1: Given nine points
A zigzag line is composed of several straight line segments. Here, the rule requests that each
line segment should pass through two or more given points.
A zigzag line may turn at some of the given points or anywhere else. There may be some given
points passed more than once.
Figure 2: Zigzag lines with three turning points.
Two zigzag lines with three turning points are depicted in Figure 2 (a) and (b) for the same
set of given points shown in Figure 1. The length of the zigzag line in Figure 2 (a) is shorter than that in Figure 2 (b). In fact, the length of the zigzag line in Figure 2 (a) is the shortest
so that it is the solution for the nine points given in Figure 1.
Another zigzag line with four turning points is depicted in Figure 3. Its length is shorter than
those in Figure 2, however, the number of turning points is greater than those in Figure 2,
and thus, it is not the solution.
Figure 3: Zigzag line with four turning points.
There are two zigzag lines that passes another set of given points depicted in Figure 4 (a) and
(b).
Both have the same number of turning points, and the line in (a) is longer than that in (b).
However, the solution is (a), because one of the segments of the zigzag line in (b) passes only
one given point, violating the rule.
Figure 4: Zigzag line with two turning points (a), and not a zigzag line concerned (b).
Your job is to write a program that solves this puzzle.
Input
The input consists of multiple datasets, followed by a line containing one zero. Each dataset
has the following format.
n
x
1
y
1
.
   .
   .
x
n
y
n
Every input item in a dataset is a non-negative integer. Items in a line are separated by a single
space.
n
is the number of the given points.
x
k
and
y
k
(
k
= 1, . . . ,
n
) indicate the position of the
k
-th
point. The order of the points is meaningless. You can assume that 2 ≤
n
≤ 10, 0 ≤
x
k
≤ 10,
and 0 ≤
y
k
≤ 10.
Output
For each dataset, the minimum number of turning points and the length of the shortest zigzag
line with that number of turning points should be printed, separated by a space in a line. The
length should be in a decimal fraction with an error less than 0.0001 (= 1.0 × 10
-4
).
You may assume that the minimum number of turning points is at most four, that is, the number
of line segments is at most five.
The example solutions for the first four datasets in the sample input are depicted in Figure 5
and 6.
Sample Input
2
0 0
10 9
4
0 0
3 1
0 3
3 3
10
2 2
4 2
6 2
2 4
4 4
6 4
2 6
4 6
6 6
3 3
10
0 0
2 0
4 0
0 2
2 2
4 2
0 4
2 4
4 4
6 8
9
0 0
1 0
3 0
0 1
1 1
3 1
...(truncated)

Submitted solutions:

code_snippet: #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<ctime>
#include<map>
#include<string>
#include<vector>
#include<set>

using namespace std;
#define For(i,l,r) for (int i = l; i <= r; ++i)
#define Cor(i,l,r) for (int i = l; i >= r; --i)
#define Fill(a,b) memset(a,b,sizeof(a))
#define FI first
#define SE second
#define MP make_pair
#define PII pair<int,int>
#define flt double
#define INF (0x3f3f3f3f)
#define MaxN 1020304
#define MaxNode 1020304
#define MD 1000000007
#define ele(x) (1 << ((x) - 1))
#define PFF pair<flt,flt>
#define UPD(a,b) { a = min(a,b); }

const flt eps = 1e-7;
int dcmp(flt x) {
	return (x < -eps) ? -1 : ((x > eps) ? 1 : 0);
}

PFF operator - (PFF a,PFF b) { return MP(a.FI - b.FI,a.SE - b.SE); }
PFF operator + (PFF a,PFF b) { return MP(a.FI + b.FI,a.SE + b.SE); }
PFF operator * (PFF a,flt b) { return MP(a.FI * b,a.SE * b); }
flt operator * (PFF a,PFF b) { return a.FI * b.SE - a.SE * b.FI; }
flt operator / (PFF a,PFF b) { 
	if (dcmp(b.FI)) return a.FI / b.FI;
	return a.SE / b.SE;
}

flt dot(PFF a,PFF b) { return a.FI * b.FI + a.SE * b.SE; }
flt mod(PFF a) {
	return sqrt(a.FI * a.FI + a.SE * a.SE); 
}

bool Longer(PFF a,PFF b,PFF c) {
	return dcmp((c - a) / (b - a) - 1.) >= 0;
}

flt xmul(PFF a,PFF b,PFF c) {
	return (c - a) * (c - b);
}

PFF GetInter(PFF a,PFF b,PFF c,PFF d) {
	PFF as = a, ae = a + b;
	PFF bs = c,be = c + d;
	flt u = xmul(as,ae,bs);
	flt v = xmul(ae,as,be);
	if (dcmp(u + v) == 0) return MP(-INF,-INF);
	return MP(bs.FI * v + be.FI * u,bs.SE * v + be.SE * u) * (1. / (u + v));
}

int n;
PFF a[MaxN]; pair<int,flt> f[1111][11][11];

int main() {
	//freopen("input.txt","r",stdin); freopen("output.txt","w",stdout);
	while (scanf("%d",&n) != EOF && n) {
		For(i,1,n) scanf("%lf%lf",&a[i].FI,&a[i].SE);
		int All = (1 << n) - 1;
		For(i,1,n) For(j,1,n) For(k,0,All) f[k][i][j] = MP(INF,INF);
		For(i,1,n) For(j,1,n) if (i != j) {
			f[ele(i) | ele(j)][i][j] = MP(0,mod(a[i] - a[j]));
		}
		For(S,0,All) For(i,1,n) For(j,1,n) if (f[S][i][j].FI < n) {
			For(k,1,n) if (!(S & ele(k))) {
				int tInc = 1;
				if (dcmp(fabs((a[k] - a[i]) * (a[i] - a[j]))) == 0 && Longer(a[j],a[i],a[k])) tInc = 0; 
				UPD(f[S | ele(k)][k][i],MP(f[S][i][j].FI + tInc,f[S][i][j].SE + mod(a[k] - a[i])));
			}
			For(k,1,n) if (!(S & ele(k))) {
				For(l,1,n) if (!(S & ele(l)) && k != l) {
					if (dcmp((a[i] - a[j]) * (a[l] - a[k])) != 0) {
						if (k == 4 && l == 3) {
							int z = k;
						}
						PFF tInter = GetInter(a[j],a[i] - a[j],a[k],a[l] - a[k]);
						if (Longer(a[j],a[i],tInter) && Longer(a[l],a[k],tInter)) {
							UPD(f[S | ele(k) | ele(l)][l][k],MP(f[S][i][j].FI + 1,f[S][i][j].SE + mod(tInter - a[i]) + mod(tInter - a[l])));
						}
					}
				}
			}
		}
		pair<int,flt> ans = MP(INF,INF);
		For(i,1,n) For(j,1,n) ans = min(ans,f[All][i][j]);
		printf("%d %.12lf\n",ans.FI,ans.SE);
	}
	return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 7388
final_rank: 4

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

struct value {
	int turn; double cost;
	bool operator!=(const value& v) const {
		return turn != v.turn || cost != v.cost;
	}
	bool operator<(const value& v) const {
		return turn != v.turn ? turn < v.turn : cost < v.cost;
	}
	value operator+(const value& v) const {
		return value{turn + v.turn, cost + v.cost};
	}
};

struct state {
	int edge, bit; value cost;
	bool operator<(const state& s) const {
		return s.cost < cost;
	}
};

int main() {
	while (true) {
		// step #1. input
		int N;
		cin >> N;
		if (N == 0) {
			break;
		}
		vector<int> X(N), Y(N);
		for (int i = 0; i < N; i++) {
			cin >> X[i] >> Y[i];
		}

		// step #2. find transitions
		auto getcross = [&](int s1, int s2, int t1, int t2) -> int {
			return (X[s2] - X[s1]) * (Y[t2] - Y[t1]) - (X[t2] - X[t1]) * (Y[s2] - Y[s1]);
		};
		vector<vector<double> > subd(N, vector<double>(N));
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				subd[i][j] = hypot(X[i] - X[j], Y[i] - Y[j]);
			}
		}
		const value INF = value{1012345678, 1.0e+99};
		vector<vector<value> > d(N * N, vector<value>(N * N, INF));
		for (int i = 0; i < N * N; i++) {
			for (int j = 0; j < N * N; j++) {
				int s1 = i / N, s2 = i % N;
				int t1 = j / N, t2 = j % N;
				if (s1 != s2 && t1 != t2) {
					int cross = getcross(s1, s2, t1, t2);
					if (cross == 0 && s2 == t1) {
						int dot = (X[s2] - X[s1]) * (X[t2] - X[t1]) + (Y[s2] - Y[s1]) * (Y[t2] - Y[t1]);
						d[i][j] = value{dot >= 0 ? 0 : 1, subd[t1][t2]};
					}
					if (cross != 0) {
						int c1 = getcross(s2, t1, s2, t2);
						int c2 = getcross(t1, s1, t1, s2);
						int f = (cross > 0 ? +1 : -1);
						if (c1 * f >= 0 && c2 * f >= 0) {
							d[i][j] = value{1, (c1 * subd[s1][s2] + (c2 + cross) * subd[t1][t2]) / cross};
						}
					}
				}
			}
		}

		// step #3. dijkstra
		vector<vector<value> > dist(N * N, vector<value>(1 << N, INF));
		priority_queue<state> que;
		vector<vector<bool> > vis(N * N, vector<bool>(1 << N, false));
		for (int i = 0; i < N * N; i++) {
			int s1 = i / N, s2 = i % N;
			if (s1 != s2) {
				int bit = (1 << s1) | (1 << s2);
				dist[i][bit] = value{0, subd[s1][s2]};
				que.push(state{i, bit, dist[i][bit]});
			}
		}
		while (!que.empty()) {
			state u = que.top();
			que.pop();
			if (!vis[u.edge][u.bit]) {
				vis[u.edge][u.bit] = true;
				for (int j = 0; j < N * N; j++) {
					int nbit = u.bit | (1 << (j / N)) | (1 << (j % N));
					if (d[u.edge][j] != INF && u.cost + d[u.edge][j] < dist[j][nbit]) {
						dist[j][nbit] = u.cost + d[u.edge][j];
						que.push(state{j, nbit, dist[j][nbit]});
					}
				}
			}
		}

		// step #4. compute answer & output
		value ans = INF;
		for (int i = 0; i < N * N; i++) {
			ans = min(ans, dist[i][(1 << N) - 1]);
		}
		cout.precision(15);
		cout << ans.turn << ' ' << fixed << ans.cost << endl;
	}

	return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 6356
final_rank: 3

code_snippet: #include <iostream>
#include <cmath>
using namespace std;

struct Point {
	double px, py;
};

Point operator+(const Point &a1, const Point &a2) {
	return Point{ a1.px + a2.px, a1.py + a2.py };
}

Point operator-(const Point &a1, const Point &a2) {
	return Point{ a1.px - a2.px, a1.py - a2.py };
}

Point operator*(const Point &a1, const double &a2) {
	return Point{ a1.px * a2, a1.py * a2 };
}

double ABS(Point A1) {
	return sqrt(A1.px * A1.px + A1.py * A1.py);
}

double crs(Point A1, Point A2) {
	return A1.px * A2.py - A1.py * A2.px;
}

// Current Checkpoint is A1->A2, Next Checkpoint is A3->A4
// What is the "cross point"?
pair<bool, Point> Cross(Point A1, Point A2, Point A3, Point A4) {
	double F1 = crs(A2 - A1, A3 - A1);
	double F2 = crs(A2 - A1, A4 - A1);
	double F3 = crs(A4 - A3, A1 - A3);
	double F4 = crs(A4 - A3, A2 - A3);
	double wari1 = -F1 / (F2 - F1);
	double wari2 = -F3 / (F4 - F3);
	
	// Check
	if (abs(F1 - F2) < 1e-6) return make_pair(false, Point{ 0.0, 0.0 });
	if (wari1 > 0.0) return make_pair(false, Point{ 0.0, 0.0 });
	if (wari2 < 1.0) return make_pair(false, Point{ 0.0, 0.0 });
	
	// Get Cross Point
	Point Target = A3 + ((A4 - A3) * wari1);
	return make_pair(true, Target);
}

// If A1, A2, A3 is in the same line and in order
bool InOrder(Point A1, Point A2, Point A3) {
	if (abs(crs(A2 - A1, A3 - A1)) > 1e-6) return false;
	Point B1 = A1 - A2;
	Point B2 = A3 - A2;
	double DOT = B1.px * B2.px + B1.py * B2.py;
	if (DOT >= 0.0) return false;
	return true;
}

int N;
Point P[19];
pair<int, double> DP[1024][12][12];

pair<int, double> solve(int mask, int pos1, int pos2) {
	if (mask == (1<<N)-1) return make_pair(0, 0.0);
	if (DP[mask][pos1][pos2].first != 1000000) return DP[mask][pos1][pos2];
	
	// Prepare
	pair<int, double> minx = make_pair(10000, -1.0);
	int bit[10];
	for (int i = 0; i < N; i++) bit[i] = ((mask / (1 << i)) % 2);
	
	// Getting 1 point at once
	for (int i = 0; i < N; i++) {
		if (bit[i] == 1) continue;
		pair<int, double> dst1 = make_pair(1, ABS(P[pos2] - P[i]));
		pair<int, double> dst2 = solve(mask+(1<<i),pos2,i);
		pair<int, double> dst3 = make_pair(dst1.first + dst2.first, dst1.second + dst2.second);
		if (InOrder(P[pos1], P[pos2], P[i]) == true) dst3.first -= 1;
		minx = min(minx, dst3);
	}
	
	// Getting 2 points at once
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (i == j || bit[i] == 1 || bit[j] == 1) continue;
			pair<bool, Point> Target = Cross(P[pos1], P[pos2], P[i], P[j]);
			if (Target.first == false) continue;
			double dst1 = ABS(P[pos2] - Target.second);
			double dst2 = ABS(P[i] - Target.second);
			double dst3 = ABS(P[i] - P[j]);
			pair<int, double> dst4 = solve(mask+(1<<i)+(1<<j), i, j);
			dst4.first += 1;
			dst4.second += (dst1 + dst2 + dst3);
			minx = min(minx, dst4);
		}
	}
	
	// Return
	//cout << mask << " " << pos1 << " " << pos2 << "  " << minx.first << " " << minx.second << endl;
	DP[mask][pos1][pos2] = minx;
	return minx;
}

int main() {
	while (true) {
		// Input
		cin >> N; if (N == 0) break;
		for (int i = 0; i < N; i++) cin >> P[i].px >> P[i].py;
		
		// Initialize
		for (int i = 0; i < (1 << N); i++) {
			for (int j = 0; j < N; j++) {
				for (int k = 0; k < N; k++) DP[i][j][k] = make_pair(1000000, -1.0);
			}
		}
		
		// Solve
		pair<int, double> Answer = make_pair(10000, -1.0);
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if (i == j) continue;
				pair<int, double> ret = solve((1<<i)+(1<<j), i, j);
				ret.second += ABS(P[i] - P[j]);
				Answer = min(Answer, ret);
			}
		}
		
		// Output
		printf("%d %.12lf\n", Answer.first, Answer.second);
	}
	return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 5796
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=998244353,MAX=55,INF=1<<20;

//幾何ライブラリ
// define double ll をするときは Point の < と == も書き換えよう！

const double eps=1e-8;
const double pi=acos((double)-1.0L);
#define equals(a,b) (fabs((a)-(b))<eps)

double torad(double deg) {return (double)(deg)*pi/180.0;}
double todeg(double ang) {return ang*180.0/pi;}

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+eps<p.x||(equals(x,p.x)&&y+eps<p.y);
        //return x<p.x||(x==p.x&&y<p.y);
    }
    
    bool operator == (const Point &p)const{
        return fabs(x-p.x)<eps/100000&&fabs(y-p.y)<eps/100000;
        //return x==p.x&&y==p.y;
    }
};

typedef Point Vector;

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;
}

struct Segment{
    Point p1,p2;
};

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;
}

Point turn(Point p,Point c,double pi){
    double q=atan2(p.y-c.y,p.x-c.x);
    q+=pi;
    p=c+Point{cos(q)*abs(p-c),sin(q)*abs(p-c)};
    
    return p;
}
//pをcを中心としてpi回転させる(1周で2π)
//p=cのときnan

//p0,p1,p2の順に見たときどうなるか？

static const int counter_clockwise=1;
static const int clockwise=-1;
static const int online_back=2;
static const int online_front=-2;
static const int 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 counter_clockwise;
    if(cross(a,b)<-eps) return clockwise;
    if(dot(a,b)<-eps) return online_back;
    if(a.norm()<b.norm()) return online_front;
    
    return on_segment;
}

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

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

bool overlap(Segment s1,Segment s2){
    int a=ccw(s1.p1,s1.p2,s2.p1),b=ccw(s1.p1,s1.p2,s2.p2);
    if(a&1||b&1) return 0;
    if(a==2){
        if(b==-2||(b==0&&!(s2.p2==s1.p1))) return 1;
        else return 0;
    }
    if(a==-2){
        if(b==2||(b==0&&!(s2.p2==s1.p2))) return 1;
        else return 0;
    }
    if(a==0){
        if(s1.p1==s2.p1){
            if(b!=2) return 1;
            else return 0;
        }
        else if(s1.p2==s2.p1){
            if(b!=-2) return 1;
            else return 0;
        }
        else return 1;
    }
    return 0;
}
//s1とs2の共通の線分(長さ0より大きい)があるかどうか

typedef Segment Line;

double getDistance(Point a,Point b){
    return abs(a-b);
}

double getDistanceLP(Line l,Point p){
    return abs(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 getDistance(Segment s1,Segment s2){
    if(intersect(s1,s2)) return 0.0;
    return min({getDistanceSP(s1,s2.p1),getDistanceSP(s1,s2.p2),getDistanceSP(s2,s1.p1),getDistanceSP(s2,s1.p2)});
}

Point getCrossPointS(Segment s1,Segment s2){
    //if(ccw(s1.p1,s1.p2,s2.p1)==0&&ccw(s1.p1,s1.p2,s2.p2)==0) return s1.p1;
    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 getCrossPointL(Line l1,Line l2){
    //if(ccw(s1.p1,s1.p2,s2.p1)==0&&ccw(s1.p1,s1.p2,s2.p2)==0) return s1.p1;
    
    Vector v1=l1.p2-l1.p1,v2=l2.p2-l2.p1;
    
    return l1.p1+v1*cross(v2,l2.p1-l1.p1)/cross(v2,v1);
}

Segment ParallelSegment(Segment s,double d){
    Vector v={-(s.p2-s.p1).y,(s.p2-s.p1).x};
    v=v/abs(v);
    
    s.p1=s.p1+v*d;
    s.p2=s.p2+v*d;
    
    return s;
}

Point naisin(Point p1,Point p2,Point p3){
    if(p1==p2&&p2==p3&&p3==p1) return p1;
    
    return (p1*abs(p2-p3)+p2*abs(p1-p3)+p3*abs(p1-p2))/(abs(p2-p3)+abs(p1-p3)+abs(p1-p2));
}

Point naisin(Line l1,Line l2,Line l3){
    //平行でない前提
    
    Point p1=getCrossPointL(l1,l2),p2=getCrossPointL(l1,l3),p3=getCrossPointL(l2,l3);
    return naisin(p1,p2,p3);
}

//ネットの適当を書いたのであってるか全く知りません→あってそう

class Circle{
public:
    Point c;
    double r;
    Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

Point CircleCenter(Point a,Point b,Point c){
    Point u=a-b,v=a-c;
    double m1=(norm(a)-norm(b))/2.0,m2=(norm(a)-norm(c))/2.0;
    
    Point res;
    if(cross(u,v)==0.0){
        res.x=1e9;
        res.y=1e9;
        
        return res;
    }
    res.x=(m1*v.y-m2*u.y)/cross(u,v);
    res.y=(m1*v.x-m2*u.x)/cross(v,u);
    
    return res;
}
//3点を通る円の中心を返す

//交わる 0
// c1がc2のinside 1
// c1がc2のoutside 2
// 交わらない 3

int not_intersect(Circle c1,Circle c2){
    double d=getDistance(c1.c,c2.c);
    double r1=c1.r,r2=c2.r;
    if(r1<r2){
        if(d<(r2-r1)) return 1;
    }
    if(r1>r2){
        if(d<(r1-r2)) return 2;
    }
    if(d<=r1+r2) return 0;
    else return 3;
}

pair<Point,Point> segCrossPpoints(Circle c,Line l){
    //assert(intersect(c,l));
    Vector pr=project(l,c.c);
    Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
    double base=sqrt(c.r*c.r-norm(pr-c.c));
    return make_pair(pr+e*base,pr-e*base);
}

double arg(Vector p){return atan2(p.y,p.x);}
Vector polar(double a,double r){return Point(cos(r)*a,sin(r)*a);}

//inside(outside)

pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
    //assert(intersect(c1,c2));
    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);
    return make_pair(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}

vector<Line> Commontangent(Circle c1,Circle c2){
    vector<Line> res;
    Point p=c2.c-c1.c;
    
    if(abs(p)>=(c1.r+c2.r)){
        Point a,b;
        a.x=c1.r*(p.x*(c1.r+c2.r)+p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        a.y=c1.r*(p.y*(c1.r+c2.r)-p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        
        b.x=c1.r*(p.x*(c1.r+c2.r)-p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        b.y=c1.r*(p.y*(c1.r+c2.r)+p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        
        res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}});
        if(!(a==b)){
            res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}});
        }
    }
    
    if(abs(p)>=abs(c1.r-c2.r)){
        Point a,b;
        a.x=c1.r*(p.x*(c1.r-c2.r)+p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        a.y=c1.r*(p.y*(c1.r-c2.r)-p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        
        b.x=c1.r*(p.x*(c1.r-c2.r)-p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        b.y=c1.r*(p.y*(c1.r-c2.r)+p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        
        res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}});
        if(!(a==b)){
            res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}});
        }
    }
    
    return res;
}

typedef vector<Point> Polygon;

/*
 IN 2
 ON 1
 OUT 0
 */

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

Polygon andrewScan(Polygon s,bool ok){
    Polygon u,l;
    sort(all(s));
    
    if(int(s.size())<3) return s;
    int n=int(s.size());
    
    u.push_back(s[0]);
    u.push_back(s[1]);
    
    l.push_back(s[n-1]);
    l.push_back(s[n-2]);
    
    if(ok){
        for(int i=2;i<n;i++){
            for(int j=int(u.size());j>=2&&ccw(u[j-2],u[j-1],s[i])==counter_clockwise;j--){
                u.pop_back();
            }
            u.push_back(s[i]);
        }
        
        for(int i=int(s.size())-3;i>=0;i--){
            for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])==counter_clockwise;j--){
                l.pop_back();
            }
            l.push_back(s[i]);
        }
    }
    
    if(!ok){
        for(int i=2;i<n;i++){
            for(int j=int(u.size());j>=2&&ccw(u[j-2],u[j-1],s[i])!=clockwise;j--){
                u.pop_back();
            }
            u.push_back(s[i]);
        }
        
        for(int i=int(s.size())-3;i>=0;i--){
            for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])!=clockwise;j--){
                l.pop_back();
            }
            l.push_back(s[i]);
        }
    }
    
    reverse(all(l));
    
    for(int i=int(u.size())-2;i>=1;i--) l.push_back(u[i]);
    
    return l;
}//ok==1なら辺の上も含める

Polygon convex_cut(const Polygon& P, const Line& l) {
    Polygon Q;
    for(int i=0;i<si(P);i++){
        Point A=P[i],B=P[(i+1)%si(P)];
        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(getCrossPointL(Line{A,B},l));
    }
    return Q;
}

double area(Point a,Point b,Point c){
    b=b-a;
    c=c-a;
    return abs(b.x*c.y-b.y*c.x)/2.0;
}

/*
 
 ll area(Polygon P){
 ll sum=0;
 for(int i=0;i<si(P);i++){
 sum+=cross(P[i],P[(i+1)%si(P)]);
 }
 return abs(sum);
 }
 
 */

// 倍

double area(Polygon &P){
    if(si(P)==0) return 0.0;
    double res=0;
    Point c={0.0,0.0};
    for(int i=0;i<si(P);i++){
        c=c+P[i];
    }
    c=c/si(P);
    
    for(int i=0;i<si(P);i++){
        res+=area(c,P[i],P[(i+1)%si(P)]);
    }
    
    return res;
}

ll gcd(ll a,ll b){
    if(b==0) return a;
    return gcd(b,a%b);
}

pair<Point,Vector> perpendicular_bisector(Point a,Point b){
    Point c=(a+b)/2;
    Vector v=b-c;
    swap(v.x,v.y);
    v.x*=-1;
    
    Point p=c;
    if(v.x==0){
        v.y=1;
        p.y=0;
    }
    else if(v.y==0){
        v.x=1;
        p.x=0;
    }
    else{
        if(v.x<0){
            v.x*=-1;
            v.y*=-1;
        }
        ll g=gcd(abs(ll(v.x)),abs(ll(v.y)));
        v.x/=g;
        v.y/=g;
        if(p.x>=0){
            ll d=p.x/v.x;
            p=p-v*d;
        }else{
            ll d=abs(p.x)/v.x;
            p=p+v*d;
            
            if(p.x<0){
                p=p+v;
            }
        }
    }
    
    return mp(p,v);
}
//2倍するなりして整数にしておくこと

pair<int,double> dp[1<<10][705];

vector<pair<int,int>> G[705];

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    while(1){
        int N;cin>>N;
        if(N==0) break;
        vector<Point> P(N);
        for(int i=0;i<N;i++) cin>>P[i].x>>P[i].y;
        
        vector<Point> use=P;
        
        for(int a=0;a<N;a++){
            for(int b=a+1;b<N;b++){
                for(int c=0;c<N;c++){
                    for(int d=c+1;d<N;d++){
                        if(isParallel(P[a],P[b],P[c],P[d])) continue;
                        auto p=getCrossPointL({P[a],P[b]},{P[c],P[d]});
                        use.push_back(p);
                    }
                }
            }
        }
        
        sort(all(use));
        use.erase(unique(all(use)),use.end());
        
        int M=si(use);
        
        for(int bit=0;bit<(1<<N);bit++){
            for(int i=0;i<M;i++){
                dp[bit][i]=mp(INF,INF);
            }
        }
        for(int i=0;i<M;i++) G[i].clear();
        
        vector<int> idP(N),dic(M,-1);
        
        for(int i=0;i<N;i++){
            for(int j=0;j<M;j++){
                if(P[i]==use[j]){
                    idP[i]=j;
                    dic[j]=i;
                }
            }
        }
        
        for(int i=0;i<M;i++){
            for(int j=i+1;j<M;j++){
                int S=0;
                for(int k=0;k<N;k++){
                    if((ccw(use[i],use[j],P[k]))==0) S|=(1<<k);
                }
                if(__builtin_popcount(S)>=2){
                    G[i].push_back(mp(j,S));
                    G[j].push_back(mp(i,S));
                }
            }
        }
        
        for(int i=0;i<N;i++){
            dp[(1<<i)][idP[i]]=mp(0,0);
        }
        
        for(int bit=0;bit<(1<<N);bit++){
            for(int i=0;i<M;i++){
                if(dp[bit][i].fi==INF) continue;
                for(auto [j,mask]:G[i]){
                    chmin(dp[bit|mask][j],mp(dp[bit][i].fi+1,dp[bit][i].se+getDistance(use[i],use[j])));
                }
            }
        }
        
        pair<int,double> ans=mp(INF,INF);
        
        for(int i=0;i<M;i++){
            chmin(ans,dp[(1<<N)-1][i]);
        }
        
        cout<<fixed<<setprecision(25)<<ans.fi-1<<" "<<ans.se<<"\n";
    }
    
}
accuracy: 1
time_ms: 210
memory_kb: 14996
final_rank: 7

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}

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

typedef complex<ld> Point;
ld dot(Point a, Point b) { return real(conj(a) * b); }
ld cross(Point a, Point b) { return imag(conj(a) * b); }
namespace std {
	bool operator<(const Point& lhs, const Point& rhs) {
		return lhs.real() == rhs.real() ? lhs.imag() < rhs.imag() : lhs.real() < rhs.real();
	}
}
struct Line {
	Point a, b;
};
struct Circle {
	Point p; ld r;
};
int ccw(Point a, Point b, Point c) {
	b -= a; c -= a;
	if (cross(b, c) > eps)return 1;//counter clockwise
	if (cross(b, c) < -eps)return -1;//clock wise
	if (dot(b, c) < 0)return 2;//c--a--b on line
	if (norm(b) < norm(c))return -2;//a--b--c on line
	return 0; //a--c--b on line
}
bool eq(ld a, ld b) {
	return abs(a - b) < eps;
}
//2直線の交差判定
bool isis_ll(Line l, Line m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}
//直線と線分の交差判定
bool isis_ls(Line l, Line s) {
	return (cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}
//点が直線上に存在するか
bool isis_lp(Line l, Point p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}
//点が線分上に存在するか
bool isis_sp(Line s, Point p) {
	//誤差がisis_lpに比べて大きいので、できるだけisis_lpを使う
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}
//線分と線分の交差判定
//bool isis_ss(Line s, Line t) {
//	return(cross(s.b - s.a, t.a - s.a)*cross(s.b - s.a, t.b - s.a) < -eps && cross(t.b - t.a, s.a - t.a)*cross(t.b - t.a, s.b - t.a) < -eps);
//}
//線分と線分の交差判定2
bool isis_ss(Line s, Line t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}
//点から直線への垂線の足
Point proj(Line l, Point p) {
	ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + t * (l.a - l.b);
}
//直線と直線の交点
//平行な２直線に対しては使うな！！！！
Point is_ll(Line s, Line t) {
	Point sv = s.b - s.a; Point tv = t.b - t.a;
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
bool sameline(Line s, Line t) {
	return abs(cross(s.b - s.a,t.b-t.a)) < eps && abs(cross(s.b-s.a,t.a-s.a)) < eps;
}

ld dp[1 << 10][1 << 11];
ld cop[1 << 10][1 << 11];

struct edge {
	int to,id; ld cost;
};
int n;
void solve() {
	vector<int> x(n), y(n);
	rep(i, n)cin >> x[i] >> y[i];
	vector<Point> p(n);
	rep(i, n)p[i] = { (ld)x[i],(ld)y[i] };
	vector<Line> vl;
	rep(i, n)Rep(j, i + 1, n) {
		Line l = { p[i],p[j] };
		bool exi = false;
		rep(j, vl.size())if (sameline(vl[j],l))exi = true;
		if (!exi)vl.push_back(l);
	}
	vector<Point> vcp;
	rep(i, n) {
		vcp.push_back(p[i]);
	}
	rep(i, vl.size())Rep(j, i + 1, vl.size()) {
		if (isis_ll(vl[i], vl[j])) {
			vcp.push_back(is_ll(vl[i], vl[j]));
		}
	}
	vector<vector<edge>> G(vcp.size());
	//vector<vector<ld>> dist(vcp.size(), vector<ld>(vcp.size()));
	//vector<vector<int>> ids(vcp.size(), vector<int>(vcp.size()));
	rep(i, vcp.size())rep(j, vcp.size()) {
		Line s = { vcp[i],vcp[j] };
		int cnt = 0;
		int cid = 0;
		rep(k, n) {
			if (isis_sp(s, p[k])) {
				//ids[i][j] |= (1 << k);
				cnt++;
				cid |= (1 << k);
			}
		}
		if (cnt >= 2) {
			G[i].push_back({ j,cid,abs(vcp[j] - vcp[i]) });
		}
		//if (cnt < 2)dist[i][j] = INF;
		//else dist[i][j] = abs(vcp[j] - vcp[i]);
	}
	rep(i, (1 << n))rep(j, vcp.size()) {
		dp[i][j] = mod;
	}
	rep(j, n)dp[0][j] = 0;
	for (int c = 0;; c++) {
		rep(i, (1 << n))rep(j, vcp.size())cop[i][j] = mod;
		rep(i, (1 << n))rep(j, vcp.size()) {
			if (dp[i][j] == mod)continue;
			for (edge e : G[j]) {
				int ni = i | e.id;
				int nj = e.to;
				chmin(cop[ni][nj], dp[i][j] + e.cost);
			}
			/*rep(k, vcp.size()) {
				int ni = i | ids[j][k];
				int nj = k;
				chmin(cop[ni][nj], dp[i][j] + dist[j][k]);
			}*/
		}
		ld ans = mod;
		rep(i, (1 << n))rep(j, vcp.size()) {
			dp[i][j] = cop[i][j];
			if (i == (1 << n) - 1)chmin(ans, dp[i][j]);
		}
		//cout << dp[785][8] << "\n";
		if (ans < mod) {
			cout << c << " " << ans << "\n";
			break;
		}
	}
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(8);
	//init_f();
	//init();
	//while(true)
	//expr();
	//init();
	//int t; cin >> t; rep(i, t)
	while (cin >> n, n) {
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 3280
memory_kb: 46648
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
const double eps = 0.000001;
const double INF = 10000;
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 abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
double dist(point P, point Q){
  return abs(Q - P);
}
double dot(point P, point Q){
  return P.x * Q.x + P.y * Q.y;
}
double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
struct line{
  point A, B;
  line(){
  }
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
bool point_on_line(point P, line L){
  return abs(cross(P - L.A, vec(L))) < eps;
}
double pos(point P, line L){
  return dot(P - L.A, vec(L));
}
bool is_parallel(line L1, line L2){
  return abs(cross(vec(L1), vec(L2))) < eps;
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
int main(){
  cout << fixed << setprecision(20);
  while (true){
    int n;
    cin >> n;
    if (n == 0){
      break;
    }
    vector<point> P(n);
    for (int i = 0; i < n; i++){
      cin >> P[i].x >> P[i].y;
    }
    vector<line> L;
    vector<int> a, b;
    int m = 0;
    for (int i = 0; i < n; i++){
      for (int j = i + 1; j < n; j++){
        bool ok = true;
        for (int k = 0; k < m; k++){
          if (point_on_line(P[i], L[k]) && point_on_line(P[j], L[k])){
            ok = false;
          }
        }
        if (ok){
          a.push_back(i);
          b.push_back(j);
          L.push_back(line(P[i], P[j]));
          m++;
        }
      }
    }
    int cnt = 0;
    vector<point> Q;
    for (int i = 0; i < m; i++){
      for (int j = i + 1; j < m; j++){
        if (!is_parallel(L[i], L[j])){
          point X = line_intersection(L[i], L[j]);
          bool ok = true;
          for (int k = 0; k < cnt; k++){
            if (dist(Q[k], X) < eps){
              ok = false;
            }
          }
          if (ok){
            Q.push_back(X);
            cnt++;
          }
        }
      }
    }
    for (int i = 0; i < n; i++){
      bool ok = true;
      for (int j = 0; j < cnt; j++){
        if (dist(Q[j], P[i]) < eps){
          ok = false;
        }
      }
      if (ok){
        Q.push_back(P[i]);
        cnt++;
      }
    }
    vector<vector<int>> id(m);
    for (int i = 0; i < m; i++){
      for (int j = 0; j < cnt; j++){
        if (point_on_line(Q[j], L[i])){
          id[i].push_back(j);
        }
      }
    }
    vector<int> p(cnt, -1);
    for (int i = 0; i < n; i++){
      for (int j = 0; j < cnt; j++){
        if (dist(Q[j], P[i]) < eps){
          p[j] = i;
        }
      }
    }
    vector<vector<tuple<double, int, int>>> E(cnt);
    for (int i = 0; i < m; i++){
      int cnt2 = id[i].size();
      vector<pair<double, int>> S(cnt2);
      for (int j = 0; j < cnt2; j++){
        S[j] = make_pair(pos(Q[id[i][j]], L[i]), id[i][j]);
      }
      sort(S.begin(), S.end());
      for (int j = 0; j < cnt2; j++){
        for (int k = j + 1; k < cnt2; k++){
          int sum = 0;
          for (int l = j; l <= k; l++){
            if (p[S[l].second] != -1){
              sum |= 1 << p[S[l].second];
            }
          }
          if (__builtin_popcount(sum) >= 2){
            int v = S[j].second;
            int w = S[k].second;
            E[v].push_back(make_tuple(dist(Q[v], Q[w]), sum, w));
            E[w].push_back(make_tuple(dist(Q[v], Q[w]), sum, v));
          }
        }
      }
    }
    vector<vector<vector<double>>> dp(6, vector<vector<double>>(cnt, vector<double>(1 << n, INF)));
    for (int i = 0; i < cnt; i++){
      dp[0][i][0] = 0;
      if (p[i] != -1){
        dp[0][i][1 << p[i]] = 0;
      }
    }
    for (int i = 0; i < 5; i++){
      for (int j = 0; j < cnt; j++){
        for (auto e : E[j]){
          double d = get<0>(e);
          int s = get<1>(e);
          int w = get<2>(e);
          for (int k = 0; k < (1 << n); k++){
            dp[i + 1][w][k | s] = min(dp[i + 1][w][k | s], dp[i][j][k] + d);
          }
        }
      }
    }
    int ans1 = 0;
    double ans2 = INF;
    for (int i = 1; i < 6; i++){
      bool ok = false;
      for (int j = 0; j < cnt; j++){
        if (dp[i][j][(1 << n) - 1] != INF){
          ans1 = i - 1;
          ans2 = min(ans2, dp[i][j][(1 << n) - 1]);
          ok = true;
        }
      }
      if (ok){
        break;
      }
    }
    cout << ans1 << ' ' << ans2 << endl;
  }
}
accuracy: 1
time_ms: 380
memory_kb: 31476
final_rank: 12

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

const int N=10;

const double EPS=1e-8;

struct Point { double x,y; };
struct Line { double a,b,c; };

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

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

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

Line makeline(Point a, Point b) {
    Line l;
    l.a=b.y-a.y;
    l.b=-(b.x-a.x);
    l.c=(b.x-a.x)*a.y-(b.y-a.y)*a.x;
    return l;
}

int intersect(Point a, Point b, Point c, Point d, Point &r) {
    Line l1=makeline(a,b),l2=makeline(c,d);
    double dd=l1.a*l2.b-l2.a*l1.b;
    if (fabs(dd)<EPS) return 0;
    r.x=(l1.b*l2.c-l2.b*l1.c)/dd;
    r.y=(l1.c*l2.a-l2.c*l1.a)/dd;
    return 1;
}

int n,z[1<<N][N][N];
double len[1<<N][N][N];
Point p[N];

int has(int mask, int i) { return (mask&(1<<i))>0; }

void savebetter(int &z1, double &len1, int z2, double len2) {
    if (z2==-1) return;
    if (z1==-1 || z1>z2 || (z1==z2 && len1>len2)) {
        z1=z2; len1=len2;
    }
}

int turn(Point a, Point b, Point c) {
    return !(fabs(cross(a,b,c))<EPS && dot(a,b,c)>0 && dot(b,a,c)<0);
}

int solve() {
    // int i,j,k,mask,a,b,m,zz;
    // double zl;
    // Point r;

    cin>>n;
    if (n==0) return 0;
    for (int i=0; i<n; i++) cin>>p[i].x>>p[i].y;

    // DP: z[mask][i][j] is the min zigzag turns to connect a set of
    // points, and the tail of the line is point i, then j.
    memset(z,-1,sizeof(z));
    for (int i=0; i<n; i++)
        for (int j=0; j<n; j++)
            if (i!=j) {
                int m=(1<<i)+(1<<j);
                savebetter(z[m][i][j],len[m][i][j],0,dist(p[i],p[j]));
            }
    for (int mask=0; mask<(1<<n); mask++)
        for (int i=0; i<n; i++)
            for (int j=0; j<n; j++)
                if (i!=j && has(mask,i) && has(mask,j)) {
                    if (z[mask][i][j]==-1) continue;

                    // direct to one point: i==j--a
                    for (int a=0; a<n; a++)
                        if (!has(mask,a) && a!=i && a!=j) {
                            int m=mask+(1<<a);
                            int zz=z[mask][i][j]+turn(p[i],p[j],p[a]);
                            double zl=len[mask][i][j]+dist(p[j],p[a]);
                            savebetter(z[m][j][a],len[m][j][a],zz,zl);
                        }

                    // zigzag to two points: i==j--a--b
                    for (int a=0; a<n; a++)
                        if (!has(mask,a) && a!=i && a!=j)
                            for (int b=0;b<n;b++)
                                if (!has(mask,b) && a!=b && b!=i && b!=j) {
                                    Point r;
                                    if (intersect(p[i],p[j],p[b],p[a],r) && !turn(r,p[j],p[i]) && !turn(r,p[a],p[b])) {
                                        int m=mask+(1<<a)+(1<<b);
                                        int zz=z[mask][i][j]+1;
                                        double zl=len[mask][i][j]+dist(r,p[j])+dist(r,p[b]);
                                        savebetter(z[m][a][b],len[m][a][b],zz,zl);
                                    }
                                }
                }

    int zz=-1;
    double zl=-1;
    int mask=(1<<n)-1;
    for (int i=0; i<n; i++)
        for (int j=0; j<n; j++)
            if (i!=j) savebetter(zz,zl,z[mask][i][j],len[mask][i][j]); 

    cout<<zz<<' '<<fixed<<setprecision(5)<<zl<<'\n';
    return 1;
}

int main() {
    while (solve());
    return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 4672
final_rank: 1

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

const int N=10;

const double EPS=1e-8;

struct Point { double x,y; };
struct Line { double a,b,c; };

int n,b[N],z[N],zmin;
double len[N],lmin;
Point p[N],s[N];

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

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

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

Line makeline(Point a, Point b) {
    Line l;
    l.a=b.y-a.y;
    l.b=-(b.x-a.x);
    l.c=(b.x-a.x)*a.y-(b.y-a.y)*a.x;
    return l;
}

int intersect(Point a, Point b, Point c, Point d, Point &r) {
    Line l1=makeline(a,b), l2=makeline(c,d);
    double dd=l1.a*l2.b-l2.a*l1.b;
    if (fabs(dd)<EPS) return 0;
    r.x=(l1.b*l2.c-l2.b*l1.c)/dd;
    r.y=(l1.c*l2.a-l2.c*l1.a)/dd;
    return 1;
}

int turn(Point a, Point b, Point c) {
    return !(fabs(cross(a,b,c))<EPS && dot(a,b,c)>0 && dot(b,a,c)<0);
}

void search(int k) {
    if (k>0 && !(z[k-1]<zmin || (z[k-1]==zmin && len[k-1]<lmin))) return;

    if (k==n) {
        zmin=z[n-1]; lmin=len[n-1];
        return;
    }

    if (k>1) {
        for (int i=0; i<n; i++)
            for (int j=0; j<n; j++)
                if (!b[i]&&!b[j]&&i!=j) {
                    b[i]=b[j]=1;
                    s[k]=p[i]; s[k+1]=p[j];
                    Point r;
                    if (intersect(s[k-2],s[k-1],s[k+1],s[k],r)) {
                        if (!turn(r,s[k-1],s[k-2]) && !turn(r,s[k],s[k+1])) {
                            z[k+1]=z[k-1]+1;
                            len[k+1]=len[k-1]+dist(r,s[k-1])+dist(r,s[k+1]);
                            search(k+2);
                        }
                    }
                    b[i]=b[j]=0;
                }
    }

    for (int i=0; i<n; i++)
        if (!b[i]) {
            b[i]=1;
            s[k]=p[i];
            z[k]=(k>1 ? z[k-1]+turn(s[k-2],s[k-1],s[k]) : 0);
            len[k]=(k>0 ? len[k-1]+dist(s[k-1],s[k]) : 0);
            search(k+1);
            b[i]=0;
        }
}

int solve() {
    cin>>n;
    if (n==0) return 0;
    for (int i=0; i<n; i++) cin>>p[i].x>>p[i].y;

    zmin=(1<<30);
    lmin=1e30;
    memset(b,0,sizeof(b));
    search(0);

    cout<<zmin<<' '<<fixed<<setprecision(5)<<lmin<<'\n';
    return 1;
}

int main() {
    while (solve());
    return 0;
}
accuracy: 1
time_ms: 2360
memory_kb: 3304
final_rank: 8

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

const int N=10;

const double EPS=1e-8;

struct Point { double x,y; };
struct Line { double a,b,c; };

int n,b[N],z[N],zmin;
double len[N],lmin;
Point p[N],s[N];

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

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

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

Line makeline(Point a, Point b) {
    Line l;
    l.a=b.y-a.y;
    l.b=-(b.x-a.x);
    l.c=(b.x-a.x)*a.y-(b.y-a.y)*a.x;
    return l;
}

int intersect(Point a, Point b, Point c, Point d, Point &r) {
    Line l1=makeline(a,b),l2=makeline(c,d);
    double dd=l1.a*l2.b-l2.a*l1.b;
    if (fabs(dd)<EPS) return 0;
    r.x=(l1.b*l2.c-l2.b*l1.c)/dd;
    r.y=(l1.c*l2.a-l2.c*l1.a)/dd;
    return 1;
}

int turn(Point a, Point b, Point c) {
    return !(fabs(cross(a,b,c))<EPS && dot(a,b,c)>0 && dot(b,a,c)<0);
}

void search(int k) {
    int i,j,tr;
    Point r;

    if (k>0 && !(z[k-1]<zmin || (z[k-1]==zmin && len[k-1]<lmin))) return;

    if (k==n) {
        zmin=z[n-1]; lmin=len[n-1];
        return;
    }

    if (k>1) {
        for (i=0;i<n;i++) for (j=0;j<n;j++) if (!b[i]&&!b[j]&&i!=j) {
            b[i]=b[j]=1;
            s[k]=p[i]; s[k+1]=p[j];
            if (intersect(s[k-2],s[k-1],s[k+1],s[k],r)) {
                if (!turn(r,s[k-1],s[k-2]) && !turn(r,s[k],s[k+1])) {
                    z[k+1]=z[k-1]+1;
                    len[k+1]=len[k-1]+dist(r,s[k-1])+dist(r,s[k+1]);
                    search(k+2);
                }
            }
            b[i]=b[j]=0;
        }
    }

    for (i=0;i<n;i++) if (!b[i]) {
        b[i]=1;
        s[k]=p[i];
        z[k]=(k>1 ? z[k-1]+turn(s[k-2],s[k-1],s[k]) : 0);
        len[k]=(k>0 ? len[k-1]+dist(s[k-1],s[k]) : 0);
        search(k+1);
        b[i]=0;
    }
}

int solve() {
    int i;

    cin>>n;
    if (n==0) return 0;
    for (i=0;i<n;i++) cin>>p[i].x>>p[i].y;

    zmin=(1<<30); lmin=1e30;
    memset(b,0,sizeof(b));
    search(0);

    cout<<zmin<<' '<<fixed<<setprecision(5)<<lmin<<endl;
    return 1;
}

int main() {
    while (solve());
    return 0;
}
accuracy: 1
time_ms: 2370
memory_kb: 3572
final_rank: 9

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;


#define EPS 0.00000001

#define SIZE 15

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	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;
	}

	double x,y;
};

typedef Point Vector;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	Point p[2];
};

int N;
int POW[SIZE];
bool FLG;
double NUM = 100;
double dp[5][1 << 10][10][10],ans;
Point point[SIZE];


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

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

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

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

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

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

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

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(x1 != x2){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}


void recursive(int state,int pre_pre,int pre,int num_turn,int max_turn,double sum_dist){

	if(sum_dist >= ans)return;

	if(state == POW[N]-1){

		ans = min(ans,sum_dist);

		FLG = true;
		return;
	}
	if(sum_dist > dp[num_turn][state][pre_pre][pre]+EPS){

		return;
	}

	int next_state;
	double next_dist;

	Line from,to,PRE,NEXT;

	from.p[0] = point[pre_pre];
	from.p[1] = point[pre];
	double	tmp_slope = calc_slope(from),tmp_slope2;
	int next_num_turn;

	//preで降り曲がる
	for(int next = 0; next < N; next++){
		if(next == pre_pre || next == pre)continue;

		next_dist = sum_dist+calc_dist(point[pre],point[next]);
		next_state = state|POW[next]; //再訪あり

		to.p[0] = point[pre];
		to.p[1] = point[next];

		next_num_turn = num_turn+1;
		tmp_slope2 = calc_slope(to);
		if(fabs(tmp_slope-tmp_slope2) < EPS){ //傾きが同じ

			//引き返しを弾く
			if(fabs(tmp_slope2-DBL_MAX) < EPS){

				if((point[pre_pre].y > point[pre].y && point[pre].y > point[next].y) ||
						(point[pre_pre].y < point[pre].y && point[pre].y < point[next].y)){

					next_num_turn -= 1;
				}

			}else{

				if((point[pre_pre].x > point[pre].x && point[pre].x > point[next].x) ||
						(point[pre_pre].x < point[pre].x && point[pre].x < point[next].x)){

					next_num_turn -= 1;
				}
			}
		}
		if(next_num_turn > max_turn)continue;

		if(dp[next_num_turn][next_state][pre][next] > next_dist+EPS){
			dp[next_num_turn][next_state][pre][next] = next_dist;

			recursive(next_state,pre,next,next_num_turn,max_turn,next_dist);
		}
	}

	if(num_turn == max_turn)return;

	if(fabs(tmp_slope-DBL_MAX) < EPS){ //垂直

		if(point[pre_pre].y > point[pre].y){

			from.p[1] = Point(point[pre].x,point[pre].y-NUM);

		}else{

			from.p[1] = Point(point[pre].x,point[pre].y+NUM);
		}

	}else{

		if(point[pre_pre].x < point[pre].x){ //右方に伸ばす

			from.p[1] = Point(point[pre].x+NUM,point[pre].y+NUM*tmp_slope);

		}else{ //左方に伸ばす

			from.p[1] = Point(point[pre].x-NUM,point[pre].y+(-NUM)*tmp_slope);
		}

	}

	PRE.p[0] = point[pre_pre];
	PRE.p[1] = point[pre];

	Line line;

	//新しい2点との交点を求める
	for(int next = 0; next < N; next++){
		if(next == pre || next == pre_pre)continue;
		for(int next_next = 0; next_next < N; next_next++){
			if(next_next == next || next_next == pre || next_next == pre_pre)continue;

			to.p[0] = point[next_next];
			to.p[1] = point[next];
			tmp_slope = calc_slope(to);

			if(fabs(tmp_slope-DBL_MAX) < EPS){ //垂直

				if(point[next_next].y > point[next].y){

					to.p[1] = Point(point[next].x,point[next].y-NUM);

				}else{

					to.p[1] = Point(point[next].x,point[next].y+NUM);
				}

			}else{

				if(point[next_next].x < point[next].x){ //右方に伸ばす

					to.p[1] = Point(point[next].x+NUM,point[next].y+NUM*tmp_slope);

				}else{ //左方に伸ばす

					to.p[1] = Point(point[next].x-NUM,point[next].y+(-NUM)*tmp_slope);
				}
			}

			NEXT.p[0] = point[next_next];
			NEXT.p[1] = point[next];

			Point cross_point = calc_Cross_Point(from,to);

			if(getDistanceSP(PRE,cross_point) < EPS || getDistanceSP(NEXT,cross_point) < EPS){
				continue;
			}
			if(calc_dist(point[pre_pre],cross_point) < calc_dist(point[pre],cross_point) ||
					calc_dist(point[next_next],cross_point) < calc_dist(point[next],cross_point)){
				continue;
			}
			next_dist = sum_dist+calc_dist(cross_point,point[pre])+calc_dist(cross_point,point[next]);
			next_dist += calc_dist(point[next],point[next_next]);

			next_state = state|(POW[next]|POW[next_next]);

			if(dp[num_turn+1][next_state][next][next_next] > next_dist+EPS){

				dp[num_turn+1][next_state][next][next_next] = next_dist;

				recursive(next_state,next,next_next,num_turn+1,max_turn,next_dist);
			}
		}
	}
}

void init(int max_count){

	for(int count = 0; count <= max_count; count++){
		for(int state = 0; state < POW[N]; state++){
			for(int pre_pre = 0; pre_pre < N; pre_pre++){
				for(int pre = 0; pre < N; pre++){

					dp[count][state][pre_pre][pre] = BIG_NUM;
				}
			}
		}
	}
}



void func(){

	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&point[i].x,&point[i].y);
	}

	int turn = -1;
	FLG = false;
	ans = BIG_NUM;

	Line line;

	//設問より、turn回数は最大で4回
	for(int max_turn = 0; max_turn <= 4; max_turn++){

		init(max_turn);

		//最初の2点を選ぶ
		for(int pre_pre = 0; pre_pre < N; pre_pre++){
			for(int pre = 0; pre < N; pre++){

				if(pre == pre_pre)continue;

				int first_state = POW[pre_pre]+POW[pre];
				double first_dist = calc_dist(point[pre_pre],point[pre]);

				line.p[0] = point[pre_pre];
				line.p[1] = point[pre];

				dp[0][first_state][pre_pre][pre] = first_dist;
				vector<Point> vec;
				vec.push_back(point[pre_pre]);
				vec.push_back(point[pre]);

				recursive(first_state,pre_pre,pre,0,max_turn,first_dist);
			}
		}

		if(FLG){
			turn = max_turn;
			break;
		}
	}

	printf("%d %.10lf\n",turn,ans);
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < SIZE; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){

		scanf("%d",&N);
		if(N == 0)break;

		func();
	}
	return 0;
}
accuracy: 1
time_ms: 4760
memory_kb: 7204
final_rank: 13

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<iomanip>
#include<math.h>
#include<complex>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<functional>
#include<assert.h>
#include<numeric>
using namespace std;
#define REP(i,m,n) for(int i=(int)(m) ; i < (int) (n) ; ++i )
#define rep(i,n) REP(i,0,n)
using ll = long long;
const int inf=1e9+7;
const ll longinf=1LL<<60 ;
const ll mod=1e9+7 ;

using ld = double;
using Point =  complex<ld>;
const ld eps = 1e-9;
const ld pi = acos(-1.0);

bool eq(ld a, ld b) {
	return (abs(a - b) < eps);
}

bool cmp(Point x,Point y){
	if(eq(x.real(),y.real()))return x.imag()<y.imag();
	return x.real()<y.real();
}

bool eqq(Point x,Point y){
	return eq(x.real(),y.real())&&eq(x.imag(),y.imag());
}
//内積
ld dot(Point a, Point b) {
	return real(conj(a)*b);
}
//外積
ld cross(Point a, Point b) {
	return imag(conj(a)*b);
}


//線分
//直線にするなら十分通い２点を端点とすればよい
class Line {
public:
	Point a, b;
};
//円
class Circle {
public:
	Point p;
	ld r;
};
//3点の位置関係
int ccw(Point a, Point b, Point c) {
	b -= a; c -= a;
	if (cross(b, c) > eps)return 1;//a,b,cが反時計回り
	if (cross(b, c) < -eps)return -1;//a,b,cが時計回り
	if (dot(b, c) < 0)return 2;//c,a,bの順に一直線
	if (norm(b) < norm(c))return -2;//a,b,cの順に一直線
	return 0;//a,c,bの順に一直線
}
//2直線の交差判定
bool isis_ll(Line l, Line m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}
//直線と線分の交差判定
bool isis_ls(Line l, Line s) {
	return (cross(l.b - l.a, s.a - l.a)*cross(l.b - l.a, s.b - l.a) < eps);
}
//点が直線上に存在するか
bool isis_lp(Line l, Point p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}
//点が線分上に存在するか
bool isis_sp(Line s, Point p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}
bool isin_sp(Line s, Point p) {
    if(eqq(s.a,p)||eqq(s.b, p))return false;
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}
//線分と線分の交差判定
bool isis_ss(Line s, Line t) {
    if (isis_sp(t, s.a) || isis_sp(t, s.b))return false;
	if (isis_sp(s, t.a) || isis_sp(s, t.b) )return false;
	return(cross(s.b - s.a, t.a - s.a)*cross(s.b - s.a, t.b - s.a) < -eps && cross(t.b - t.a, s.a - t.a)*cross(t.b - t.a, s.b - t.a) < -eps);
}
//点から直線への垂線の足
Point proj(Line l, Point p) {
	ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + t * (l.a - l.b);
}

Point cont(Line l, Point p){
	return 2.0*proj(l, p) - p;
}

//直線と直線の交点
//平行な２直線に対しては使うな！！！！
Point is_ll(Line s, Line t) {
	Point sv = s.b - s.a; Point tv = t.b - t.a;
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
//直線と点の距離
ld dist_lp(Line l, Point p) {
	return abs(p - proj(l, p));
}
//直線と直線の距離
ld dist_ll(Line l, Line m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}
//線分と直線の距離
ld dist_ls(Line l, Line s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}
//線分と点の距離
ld dist_sp(Line s, Point p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(p - r) : min(abs(p - s.a), abs(p - s.b));
}
//線分と線分の距離
ld dist_ss(Line s, Line t) {
	if (isis_ss(s, t))return 0;
	return min({ dist_sp(s,t.a),dist_sp(s,t.b),dist_sp(t,s.a),dist_sp(t,s.b) });
}

bool included(vector<Point> pol, Point p){
    int n=pol.size();
    ld sum=0;
    rep(i,n){
        Point cur=pol[i], nxt=pol[(i+1)%n];
        if(isis_sp({cur,nxt},p))return true;
        sum+=arg((nxt-p)/(cur-p));
    }
    return abs(sum)>1;
}

struct info{
    int pre,cur,mask;
    bool operator<(const info& rhs)const{
        return make_tuple(pre,cur,mask)<make_tuple(rhs.pre,rhs.cur,rhs.mask);

    };
};
void solve(int n){
    Point p[n];
    rep(i,n){
        int x,y;
        cin>>x>>y;
        p[i]=Point(x,y);
    }
    int m=n*(n-1);
    vector<pair<int,int>> l;
    vector<int> mask;
    rep(i,n)rep(j,n){
        if(i==j)continue;
        l.push_back({i,j});
        int b=0;
        Line ls={p[i],p[j]};
        rep(k,n){
            if(isis_sp(ls,p[k]))b|=(1<<k);
        }
        mask.push_back(b);
    }
    pair<int,ld> dist[1<<n][n][n];
    rep(i,n)rep(j,n)rep(k,1<<n){
        dist[k][i][j]={inf,inf};
    }
    using T = pair<pair<int,ld>,info> ;
    priority_queue<T,vector<T>,greater<T>> que;
    rep(i,m){
        info in = {l[i].first, l[i].second,mask[i]};
        dist[mask[i]][l[i].first][l[i].second]={0,abs(p[l[i].second]-p[l[i].first])};
        que.push({dist[mask[i]][l[i].first][l[i].second],in});
    }
    while(que.size()){
        auto t = que.top();que.pop();
        int mas=t.second.mask, pre=t.second.pre, cur=t.second.cur;
        pair<int,ld> d = t.first;
        if(dist[mas][pre][cur]<d)continue;
        rep(i,m){
            if(abs(cross(p[pre]-p[cur],p[l[i].first]-p[l[i].second]))<eps)continue;
            Point turn = is_ll({p[pre],p[cur]},{p[l[i].first],p[l[i].second]});
            if(abs(p[cur]-turn)>eps&&ccw(p[pre],p[cur],turn)!=-2)continue;
            if(abs(p[l[i].first]-turn)>eps&&ccw(p[l[i].second],p[l[i].first],turn)!=-2)continue;
            double nd = abs(p[cur]-turn)+abs(p[l[i].second]-p[l[i].first])+abs(p[l[i].first]-turn);
            int nmask=mas|mask[i];
            if(dist[nmask][l[i].first][l[i].second] > make_pair(d.first+1, d.second+nd)){
                dist[nmask][l[i].first][l[i].second] = make_pair(d.first+1, d.second+nd);
                que.push({dist[nmask][l[i].first][l[i].second],{l[i].first, l[i].second,nmask}});
            }
        }
    }
    pair<int,ld> ans={inf,inf};
    rep(i,n)rep(j,n){
        ans=min(ans,dist[(1<<n)-1][i][j]);
    }
    cout<<ans.first<<" "<<ans.second<<endl;
}

int main(){
    int n;
    cout<<fixed<<setprecision(10);
    while(cin>>n,n!=0)solve(n);
    return 0;
}
accuracy: 1
time_ms: 2520
memory_kb: 5620
final_rank: 10

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<iomanip>
#include<math.h>
#include<complex>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<functional>
#include<assert.h>
#include<numeric>
using namespace std;
#define REP(i,m,n) for(int i=(int)(m) ; i < (int) (n) ; ++i )
#define rep(i,n) REP(i,0,n)
using ll = long long;
const int inf=1e9+7;
const ll longinf=1LL<<60 ;
const ll mod=1e9+7 ;

using ld = double;
using Point =  complex<ld>;
const ld eps = 1e-9;
const ld pi = acos(-1.0);

bool eq(ld a, ld b) {
	return (abs(a - b) < eps);
}

bool cmp(Point x,Point y){
	if(eq(x.real(),y.real()))return x.imag()<y.imag();
	return x.real()<y.real();
}

bool eqq(Point x,Point y){
	return eq(x.real(),y.real())&&eq(x.imag(),y.imag());
}
//内積
ld dot(Point a, Point b) {
	return real(conj(a)*b);
}
//外積
ld cross(Point a, Point b) {
	return imag(conj(a)*b);
}


//線分
//直線にするなら十分通い２点を端点とすればよい
class Line {
public:
	Point a, b;
};
//円
class Circle {
public:
	Point p;
	ld r;
};
//3点の位置関係
int ccw(Point a, Point b, Point c) {
	b -= a; c -= a;
	if (cross(b, c) > eps)return 1;//a,b,cが反時計回り
	if (cross(b, c) < -eps)return -1;//a,b,cが時計回り
	if (dot(b, c) < 0)return 2;//c,a,bの順に一直線
	if (norm(b) < norm(c))return -2;//a,b,cの順に一直線
	return 0;//a,c,bの順に一直線
}
//2直線の交差判定
bool isis_ll(Line l, Line m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}
//直線と線分の交差判定
bool isis_ls(Line l, Line s) {
	return (cross(l.b - l.a, s.a - l.a)*cross(l.b - l.a, s.b - l.a) < eps);
}
//点が直線上に存在するか
bool isis_lp(Line l, Point p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}
//点が線分上に存在するか
bool isis_sp(Line s, Point p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}
bool isin_sp(Line s, Point p) {
    if(eqq(s.a,p)||eqq(s.b, p))return false;
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}
//線分と線分の交差判定
bool isis_ss(Line s, Line t) {
    if (isis_sp(t, s.a) || isis_sp(t, s.b))return false;
	if (isis_sp(s, t.a) || isis_sp(s, t.b) )return false;
	return(cross(s.b - s.a, t.a - s.a)*cross(s.b - s.a, t.b - s.a) < -eps && cross(t.b - t.a, s.a - t.a)*cross(t.b - t.a, s.b - t.a) < -eps);
}
//点から直線への垂線の足
Point proj(Line l, Point p) {
	ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + t * (l.a - l.b);
}

Point cont(Line l, Point p){
	return 2.0*proj(l, p) - p;
}

//直線と直線の交点
//平行な２直線に対しては使うな！！！！
Point is_ll(Line s, Line t) {
	Point sv = s.b - s.a; Point tv = t.b - t.a;
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
//直線と点の距離
ld dist_lp(Line l, Point p) {
	return abs(p - proj(l, p));
}
//直線と直線の距離
ld dist_ll(Line l, Line m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}
//線分と直線の距離
ld dist_ls(Line l, Line s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}
//線分と点の距離
ld dist_sp(Line s, Point p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(p - r) : min(abs(p - s.a), abs(p - s.b));
}
//線分と線分の距離
ld dist_ss(Line s, Line t) {
	if (isis_ss(s, t))return 0;
	return min({ dist_sp(s,t.a),dist_sp(s,t.b),dist_sp(t,s.a),dist_sp(t,s.b) });
}

bool included(vector<Point> pol, Point p){
    int n=pol.size();
    ld sum=0;
    rep(i,n){
        Point cur=pol[i], nxt=pol[(i+1)%n];
        if(isis_sp({cur,nxt},p))return true;
        sum+=arg((nxt-p)/(cur-p));
    }
    return abs(sum)>1;
}

struct info{
    int pre,cur,mask;
    bool operator<(const info& rhs)const{
        return make_tuple(pre,cur,mask)<make_tuple(rhs.pre,rhs.cur,rhs.mask);

    };
};
void solve(int n){
    Point p[n];
    rep(i,n){
        int x,y;
        cin>>x>>y;
        p[i]=Point(x,y);
    }
    int m=n*(n-1);
    vector<pair<int,int>> l;
    vector<int> mask;
    rep(i,n)rep(j,n){
        if(i==j)continue;
        l.push_back({i,j});
        int b=0;
        Line ls={p[i],p[j]};
        rep(k,n){
            if(isis_sp(ls,p[k]))b|=(1<<k);
        }
        mask.push_back(b);
    }
    pair<int,ld> dist[1<<n][n][n];
    rep(i,n)rep(j,n)rep(k,1<<n){
        dist[k][i][j]={inf,inf};
    }
    using T = pair<pair<int,ld>,info> ;
    priority_queue<T,vector<T>,greater<T>> que;
    rep(i,m){
        info in = {l[i].first, l[i].second,mask[i]};
        dist[mask[i]][l[i].first][l[i].second]={0,abs(p[l[i].second]-p[l[i].first])};
        que.push({dist[mask[i]][l[i].first][l[i].second],in});
    }
    while(que.size()){
        auto t = que.top();que.pop();
        int mas=t.second.mask, pre=t.second.pre, cur=t.second.cur;
        pair<int,ld> d = t.first;
        if(dist[mas][pre][cur]<d)continue;
        rep(i,m){
            if(abs(cross(p[pre]-p[cur],p[l[i].first]-p[l[i].second]))<eps)continue;
            Point turn = is_ll({p[pre],p[cur]},{p[l[i].first],p[l[i].second]});
            if(isin_sp({p[pre],p[cur]},turn))continue;
            if(isin_sp({p[l[i].first],p[l[i].second]},turn))continue;
            if(abs(p[cur]-turn)>eps&&ccw(p[pre],p[cur],turn)!=-2)continue;
            if(abs(p[l[i].first]-turn)>eps&&ccw(p[l[i].second],p[l[i].first],turn)!=-2)continue;
            double nd = abs(p[cur]-turn)+abs(p[l[i].second]-p[l[i].first])+abs(p[l[i].first]-turn);
            int nmask=mas|mask[i];
            if(dist[nmask][l[i].first][l[i].second] > make_pair(d.first+1, d.second+nd)){
                dist[nmask][l[i].first][l[i].second] = make_pair(d.first+1, d.second+nd);
                que.push({dist[nmask][l[i].first][l[i].second],{l[i].first, l[i].second,nmask}});
            }
        }
    }
    pair<int,ld> ans={inf,inf};
    rep(i,n)rep(j,n){
        ans=min(ans,dist[(1<<n)-1][i][j]);
    }
    cout<<ans.first<<" "<<ans.second<<endl;
}

int main(){
    int n;
    cout<<fixed<<setprecision(10);
    while(cin>>n,n!=0)solve(n);
    return 0;
}
accuracy: 1
time_ms: 3360
memory_kb: 5576
final_rank: 11

code_snippet: #include <cstdio>
#include <iostream>
#include <vector>
#include <complex>
#include <utility>
#include <algorithm>
#include <numeric>
using namespace std;
typedef complex<double> P;
typedef pair<P,P> L;
#define X real()
#define Y imag()
const double INF = (1e15), EPS = (1e-8);
const pair<int,double> init(8,INF);
P Points[10];
pair<int,double> ans, DP[2];

inline double dot(P a, P b){ return a.X*b.X + a.Y*b.Y;}
inline double cross(P a, P b){ return a.X*b.Y - a.Y*b.X;}

inline P intersection(L a, L b){
  P bf = b.first, af = a.first-bf, as = a.second-bf, bs = b.second-bf;
  return af + bf + cross(bs,af)/(-cross(bs,as)+cross(bs,af))*(as-af);
}

inline bool on_line(P a, P b, P c){
  b -= a, c -= a;
  if(cross(b,c) > EPS) return false;
  if(cross(b,c) < -EPS) return false;
  if(dot(b,c) < 0) return false;
  if(norm(b) + EPS < norm(c)) return false;
  return true;
}

int main(){
  int n;
  while(cin >> n, n){
    ans = init;
    for(int i = 0; i < n; ++i){
      double x, y;
      cin >> x >> y;
      Points[i] = P(x,y);
    }
    vector<int> perm(n);
    iota(perm.begin(), perm.end(), 0);
    do{
      if(perm[0] == n-1) break;
      if(perm[0] > perm.back()) continue;
      DP[1] = init;
      DP[0] = pair<int,double>(0,abs(Points[perm[1]]-Points[perm[0]]));
      for(int i = 1; i < n-1; ++i){
        if(DP[0] >= ans && DP[1] >= ans) break;
        P prev = Points[perm[i-1]], cur = Points[perm[i]], nex = Points[perm[i+1]];
        int c = !on_line(prev, nex, cur);
        pair<int,double> val = DP[0];
        double l = abs(nex-cur);
        DP[1].second += l;
        DP[0].second += l;
        DP[0].first += c;
        DP[0] = min(DP[0],DP[1]);
        if(i == n-2) break;
        P nexx = Points[perm[i+2]];
        if(norm(cross(cur-prev,nexx-nex)) < EPS or on_line(prev,nex,cur) or on_line(cur,nexx,nex)){
          DP[1] = init;
          continue;
        }
        P cp = intersection(L(prev,cur),L(nex,nexx));
        if((!on_line(cp,nexx,nex)) or (!on_line(prev,cp,cur))){
          DP[1] = init;
          continue;
        }
        DP[1] = val;
        ++DP[1].first;
        DP[1].second += abs(cp-cur) + abs(cp-nex);
      }
      ans = min(ans, DP[0]);
    }while(next_permutation(perm.begin(), perm.end()));
    printf("%d %.5f\n", ans.first, ans.second);
  }
  return 0;
}
accuracy: 1
time_ms: 7990
memory_kb: 3168
final_rank: 14

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
#include <map>
#include <set>
#include <utility>
#include <queue>
using namespace std;
const double EPS = 1e-10;
const double INF = 1e12;
const double PI = acos(-1);
#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 !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<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 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(cross(s[0]-p, s[1]-p))<EPS  && dot(s[0]-p, s[1]-p)<EPS;
}
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]);
}

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]);
}

struct info{
    int pos,bit,turn;
    double dist;
    info(int p, int b, int t, double d):pos(p),bit(b),turn(t),dist(d){}
    info(){}
    bool operator <(const info &a) const{
        return (turn!=a.turn)? turn>a.turn: dist>a.dist;
    }
};
bool eqpos(const info &a, const info &b){
    return a.pos == b.pos;
}
pair<vector<vector<info> >, VP> exarrangement(const vector<L> &l, const VP &p, const set<P> &ps){
    vector<VP> cp(l.size());
    VP plist = p;
    for(int i=0; i<(int)l.size(); i++){
        for(int j=i+1; j<(int)l.size(); j++){
            if(!isParallel(l[i], l[j])){
                P cpij = crosspointLL(l[i], l[j]);
                cp[i].push_back(cpij);
                cp[j].push_back(cpij);
                plist.push_back(cpij);
            }
        }
        for(int j=0; j<(int)p.size(); j++){
            if(intersectLP(l[i], p[j])){
                cp[i].push_back(p[j]);
            }
        }
        sort(cp[i].begin(), cp[i].end());
        cp[i].erase(unique(cp[i].begin(), cp[i].end()), cp[i].end());
    }
    sort(plist.begin(), plist.end());
    plist.erase(unique(plist.begin(), plist.end()), plist.end());

    int n = plist.size();
    map<P, int> conv;
    for(int i=0; i<n; i++){
        conv[plist[i]] = i;
    }
    vector<vector<info> > adj(n);
    for(int i=0; i<(int)cp.size(); i++){
        for(int j=0; j<(int)cp[i].size(); j++){
            for(int k=j+1; k<(int)cp[i].size(); k++){
                int jidx = conv[cp[i][j]];
                int kidx = conv[cp[i][k]];
                double dist = abs(cp[i][j] -cp[i][k]);
                int bit = 0;
                L edge(cp[i][j], cp[i][k]);
                for(int t=0; t<(int)p.size(); t++){
                    if(intersectSP(edge, p[t])){
                        bit |= 1<<t;
                    }
                }
                adj[jidx].push_back(info(kidx, bit, 0, dist));
                adj[kidx].push_back(info(jidx, bit, 0, dist));
            }
        }
    }
    for(int i=0; i<n; i++){
        sort(adj[i].begin(), adj[i].end());
        adj[i].erase(unique(adj[i].begin(), adj[i].end(), eqpos), adj[i].end());
    }
    return make_pair(adj, plist);
}

pair<vector<vector<info> >, VP> makegraph(const VP &p){
    vector<L> lines;
    for(int i=0; i<(int)p.size(); i++){
        for(int j=i+1; j<(int)p.size(); j++){
            lines.push_back(L(p[i], p[j]));
        }
    }
    set<P> ps;
    for(int i=0; i<(int)p.size(); i++){
        ps.insert(p[i]);
    }
    return exarrangement(lines, p, ps);
}

int main(){
    while(1){
        int n;
        cin >> n;
        if(n==0) break;

        VP p(n);
        for(int i=0; i<n; i++){
            int x,y;
            cin >> x >> y;
            p[i] = P(x, y);
        }
        
        pair<vector<vector<info> >, VP> ret = makegraph(p);
        vector<vector<info> > &adj = ret.first;
        VP &plist = ret.second;
        priority_queue<info> wait;
        vector<vector<pair<int, double> > > mincost(plist.size(), vector<pair<int, double> >(1<<n, make_pair(100, INF)));
        for(int i=0; i<n; i++){
            int pidx = lower_bound(plist.begin(), plist.end(), p[i]) -plist.begin();
            wait.push(info(pidx, 0, -1, 0));
            mincost[i][1<<i] = make_pair(-1, 0);
        }

        while(!wait.empty()){
            int pos = wait.top().pos;
            int bit = wait.top().bit;
            int turn = wait.top().turn;
            double dist = wait.top().dist;
            wait.pop();
            if(mincost[pos][bit] < make_pair(turn, dist)) continue;
            if(bit == (1<<n)-1) continue;

            for(info &next: adj[pos]){
                int npos = next.pos;
                int nbit = bit | next.bit;
                double ndist = dist +next.dist;
                pair<int, double> cost(turn+1, ndist);
                if(cost < mincost[npos][nbit]){
                    wait.push(info(npos, nbit, turn+1, ndist));
                    mincost[npos][nbit] = cost;
                }
            }
        }

        pair<int, double> ans(100, INF);
        for(int i=0; i<(int)plist.size(); i++){
            ans = min(ans, mincost[i][(1<<n)-1]);
        }
        cout << fixed << setprecision(10);
        cout << ans.first << " " << ans.second << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 5010
memory_kb: 33000
final_rank: 18

code_snippet: #include<bits/stdc++.h>
#define MAX 2500
#define inf 1<<29
#define linf 1e18
#define eps (1e-8)
#define mod 1000000007
#define pi M_PI
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,int> pdi;
typedef pair<int,double> pid;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

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 k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return (x!=p.x ? x<p.x : y<p.y);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

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);}

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

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

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;
}

Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

vector<Point> unique(vector<Point> vp){
  sort(vp.begin(),vp.end());
  vector<Point> res;
  res.push_back(vp[0]);
  for(int i=1;i<vp.size();i++){
    if(!(vp[i]==res.back()))res.push_back(vp[i]);
  }
  return res;
}

class State{
  public:
    int index,bit,num;
    double dis;
    State(int index,int bit,int num,double dis):
      index(index),bit(bit),num(num),dis(dis){}
    bool operator<(State s)const{
      return s.num!=num ? s.num<num : s.dis-dis<-eps; 
     }
};

int n;
vector<Point> vp,sp;
vector<pii> e[MAX];
pid d[MAX][1<<10];

void init(){
  vp.clear();
  sp.clear();
  FOR(i,0,MAX){
    e[i].clear();
    FOR(j,0,1<<10)d[i][j]=mp(inf,inf);
  }
}

bool comp(pid a,pid b){
  return a.f!=b.f ? a.f<b.f : a.s-b.s<-eps;
}

pid dijkstra(){
  priority_queue<State> pq;
  FOR(i,0,MAX)FOR(j,0,1<<n)d[i][j]=mp(inf,inf);
  FOR(i,0,sp.size()){
    d[i][0]=mp(0,0);
    pq.push(State(i,0,0,0));
  }

  while(pq.size()){
    State u=pq.top();
    pq.pop();
    if(u.bit==((1<<n)-1))return mp(u.num,u.dis);
    if(comp(d[u.index][u.bit],mp(u.num,u.dis)))continue; 

    FOR(i,0,e[u.index].size()){
      if(i==u.index)continue;
      pii next=e[u.index][i];
      int nbit=(u.bit|next.s);
      double cost=abs(sp[u.index]-sp[next.f]);
      if(comp(mp(d[u.index][u.bit].f+1,d[u.index][u.bit].s+cost),
           d[next.f][nbit])){
        d[next.f][nbit]=mp(d[u.index][u.bit].f+1,
                      d[u.index][u.bit].s+cost);
        pq.push(State(next.f,nbit,d[next.f][nbit].f,d[next.f][nbit].s));
      }
    }
  }
  return mp(inf,inf);
}

pid solve(){
  vector<Line> vl; 
  FOR(i,0,n)FOR(j,i+1,n)vl.pb(Line(vp[i],vp[j]));
  FOR(i,0,n)sp.pb(vp[i]);
  FOR(i,0,vl.size()){
    FOR(j,i+1,vl.size()){
      if(isParallel(vl[i],vl[j]))continue;
      sp.pb(getCrossPointLL(vl[i],vl[j]));
    }
  }
  sp=unique(sp);
  FOR(i,0,sp.size()){
    FOR(j,0,sp.size()){
      if(i==j)continue;
      int bits=0;
      int c=0;
      FOR(k,0,n){
        if(ccw(sp[i],sp[j],vp[k])==0){
          bits+=(1<<k);
          c++;
        }
      }
      if(c>=2)e[i].pb(mp(j,bits));
    }
  }
  return dijkstra();
}

int main()
{
  while(1){
    cin>>n;
    init();
    if(n==0)break;
    FOR(i,0,n){
      int x,y;
      cin>>x>>y;
      vp.pb(Point(x,y));
    }
    pid ans=solve();
    cout<<ans.f-1<<" ";
    pd(ans.s);
  }
  return 0;
}
accuracy: 1
time_ms: 1580
memory_kb: 48456
final_rank: 15

code_snippet: #include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const double EPS = 1e-10;
const double INF = 1e+10;
const double PI = acos(-1);
int sig(double r) { return (r < -EPS) ? -1 : (r > +EPS) ? +1 : 0; }
inline double ABS(double a){return max(a,-a);}
struct Pt {
	double x, y;
	Pt() {}
	Pt(double x, double y) : x(x), y(y) {}
	Pt operator+(const Pt &a) const { return Pt(x + a.x, y + a.y); }
	Pt operator-(const Pt &a) const { return Pt(x - a.x, y - a.y); }
	Pt operator*(const Pt &a) const { return Pt(x * a.x - y * a.y, x * a.y + y * a.x); }
	Pt operator-() const { return Pt(-x, -y); }
	Pt operator*(const double &k) const { return Pt(x * k, y * k); }
	Pt operator/(const double &k) const { return Pt(x / k, y / k); }
	double ABS() const { return sqrt(x * x + y * y); }
	double abs2() const { return x * x + y * y; }
	double arg() const { return atan2(y, x); }
	double dot(const Pt &a) const { return x * a.x + y * a.y; }
	double det(const Pt &a) const { return x * a.y - y * a.x; }
};
double tri(const Pt &a, const Pt &b, const Pt &c) { return (b - a).det(c - a); }
int iSP(Pt a, Pt b, Pt c) {
	int s = sig((b - a).det(c - a));
	if (s) return s;
	if (sig((b - a).dot(c - a)) < 0) return -2; // c-a-b
	if (sig((a - b).dot(c - b)) < 0) return +2; // a-b-c
	return 0;
}
int iLL(Pt a, Pt b, Pt c, Pt d) {
	if (sig((b - a).det(d - c))) return 1; // intersect
	if (sig((b - a).det(c - a))) return 0; // parallel
	return -1; // correspond
}
Pt pLL(Pt a, Pt b, Pt c, Pt d) {
	b = b - a; d = d - c; return a + b * (c - a).det(d) / b.det(d);
}

pair<int,double> dp[1<<10][11][11];
Pt p[12];
int main(){
	int a;
	while(scanf("%d",&a),a){
		for(int i=0;i<a;i++){
			double x,y;
			scanf("%lf%lf",&x,&y);
			p[i]=Pt(x,y);
		}
		for(int i=0;i<(1<<a);i++)for(int j=0;j<a;j++)for(int k=0;k<a;k++)
			dp[i][j][k]=make_pair(999999999,999999999);
		for(int i=0;i<a;i++){
			for(int j=0;j<a;j++){
				if(i==j)continue;
				int to=(1<<i)+(1<<j);
				for(int k=0;k<a;k++){
					if(iSP(p[i],p[k],p[j])==2)to|=(1<<k);
				}
				dp[to][i][j]=make_pair(0,(p[i]-p[j]).ABS());
			}
		}
		for(int i=0;i<(1<<a);i++){
			for(int j=0;j<a;j++)for(int k=0;k<a;k++){
				if(dp[i][j][k].first>99999)continue;
				for(int l=0;l<a;l++){
					int to=i|(1<<l);
					for(int m=0;m<a;m++){
						if(iSP(p[k],p[m],p[l])==2)to|=(1<<m);
					}
					dp[to][k][l]=min(dp[to][k][l],make_pair(dp[i][j][k].first+1,dp[i][j][k].second+(p[k]-p[l]).ABS()));
				}
				for(int l=0;l<a;l++)for(int m=0;m<a;m++){
					if(l==m)continue;
					if(iLL(p[j],p[k],p[l],p[m])!=1)continue;
					Pt t=pLL(p[j],p[k],p[l],p[m]);
					if(iSP(p[j],p[k],t)==2&&iSP(t,p[l],p[m])==2){
						int to=i|(1<<l)|(1<<m);
						for(int n=0;n<a;n++){
							if(iSP(t,p[n],p[m])==2)to|=(1<<n);
						}
						dp[to][l][m]=min(dp[to][l][m],make_pair(dp[i][j][k].first+1,dp[i][j][k].second+(t-p[k]).ABS()+(p[m]-t).ABS()));
					}
				}
			}
		}
		pair<int,double>ret=make_pair(999999999,99999999);
		for(int i=0;i<a;i++)for(int j=0;j<a;j++)ret=min(ret,dp[(1<<a)-1][i][j]);
		printf("%d %.12f\n",ret.first,ret.second);
	}
}
accuracy: 1
time_ms: 1890
memory_kb: 3012
final_rank: 6

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <iterator>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) container.begin(), container.end()
#define RALL(container) container.rbegin(), container.rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
#include <complex>
#include <cmath>
#define EPS 1.0e-10
#define PI 3.1415926535897932384 

// 実数の符号関数
inline int signum(double x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
//XY座標
#define X real()
#define Y imag()
// 点
typedef complex<double> P;
 

// 線分・半直線・直線
struct L { 
	P pos, dir;
	L(){}
	L(P p, P d):pos(p),dir(d){}
};
 
// 多角形
typedef vector<P> G;
 
// 円
struct C { P p; double r; };

// std::norm はabs(p)*abs(p)なので遅い
inline double norm(P p){
	return p.X*p.X+p.Y*p.Y;
}

// 二つのベクトルの内積を計算する
inline double inp(const P& a, const P& b) {
	return (conj(a)*b).real();
}
 
// 二つのベクトルの外積を計算する
inline double outp(const P& a, const P& b) {
	return (conj(a)*b).imag();
}

inline int ccw(const P& p, const P& r, const P& s) {
    P a(r-p), b(s-p);
    int sgn = signum(outp(a, b));
    if (sgn != 0)
        return sgn;
    if (a.real()*b.real() < -EPS || a.imag()*b.imag() < -EPS)
        return -1;
    if (norm(a) < norm(b) - EPS)
        return 1;
    return 0;
}

// ベクトルpをベクトルbに射影したベクトルを計算する
inline P proj(const P& p, const P& b) {
	return b*inp(p,b)/norm(b);
}
 
// 点pから直線lに引いた垂線の足となる点を計算する
inline P perf(const L& l, const P& p) {
	L m(l.pos - p, l.dir);
	return (p + (m.pos - proj(m.pos, m.dir)));
}
 
// 線分sを直線bに射影した線分を計算する
inline L proj(const L& s, const L& b) {
	 return L(perf(b, s.pos), proj(s.dir, b.dir));
}

bool ll_intersects(const L& l, const L& m) {
    return (abs(outp(l.dir, m.dir)) > EPS || abs(outp(l.dir, m.pos-l.pos)) < EPS);
}
P line_cross(const L& l, const L& m) {
    double num = outp(m.dir, m.pos-l.pos);
    double denom = outp(m.dir, l.dir);
    return P(l.pos + l.dir*num/denom);
}
bool ls_intersects(const L& l, const L& s) {
    return (signum(outp(l.dir, s.pos-l.pos)) *
            signum(outp(l.dir, s.pos+s.dir-l.pos)) <= 0);
}
bool sp_intersects(const L& s, const P& p) {
    return ( abs(s.pos - p) + abs(s.pos + s.dir - p) - abs(s.dir) < EPS );
}
bool ss_intersects(const L& s, const L& t) {
    return (ccw(s.pos, s.pos+s.dir, t.pos) *
            ccw(s.pos, s.pos+s.dir, t.pos+t.dir) <= 0 &&
            ccw(t.pos, t.pos+t.dir, s.pos) *
            ccw(t.pos, t.pos+t.dir, s.pos+s.dir) <= 0);
}
double lp_distance(const L& l, const P& p) {
    return abs(outp(l.dir, p-l.pos) / abs(l.dir));
}
double ll_distance(const L& l, const L& m) {
    return (ll_intersects(l, m) ? 0 : lp_distance(l, m.pos));
}
double ls_distance(const L& l, const L& s) {
    if (ls_intersects(l, s))
        return 0;
    return min(lp_distance(l, s.pos), lp_distance(l, s.pos+s.dir));
}
double sp_distance(const L& s, const P& p) {
    const P r = perf(s, p);
    const double pos = ((r-s.pos)/s.dir).real();
    if (-EPS <= pos && pos <= 1 + EPS)
        return norm(r - p);
    return min(norm(s.pos - p),
               norm(s.pos+s.dir - p));
}
double ss_distance(const L& s, const L& t) {
    if (ss_intersects(s, t))
        return 0;
    return (max(sp_distance(s, t.pos), max(sp_distance(s, t.pos+t.dir), max(sp_distance(t, s.pos), sp_distance(t, s.pos+s.dir)))));
}


const int INF = 1<<28;
const int MOD = 1000000007;


int n;

double dp[1<<10][11][25][25];
pii pp[11][11];

main(){
	int i,j;
	while(cin >> n, n){
		REP(i, 1<<n)REP(j, n)REP(k, 22)REP(l, 22) dp[i][j][k][l] = 10000;
		double ans(10000);
		vector<P> p(n);
		REP(i, n){
			double x, y;
			cin >> x >> y;
			p[i] = P(x, y);
		}
		vector<pii> dr;
		REP(i, n)REP(j, i){
			P dir = p[j]-p[i];
			int g = __gcd((int)abs(dir.X), (int)abs(dir.Y));
			pp[i][j] = pii((int)dir.X/g, (int)dir.Y/g);
			pp[j][i] = pii(-(int)dir.X/g, -(int)dir.Y/g);
			dr.emplace_back((int)dir.X/g, (int)dir.Y/g);
			dr.emplace_back(-(int)dir.X/g, -(int)dir.Y/g);
		}
		sort(ALL(dr));
		UNIQUE(dr);
		REP(i, 1<<n)REP(j, n)REP(d, dr.size()){
			int dx = dr[d].first;
			int dy = dr[d].second;
			double &t = dp[i][j][dx+10][dy+10];
			
			if(i == (1<<j)) t = .0;
			if(t > 9000) continue;
//			printf("dp[%d][%d][%d][%d] = (%d, %f)\n", i, j, dx, dy, t.first, t.second);
			if(i == (1<<n)-1){
				ans = min(ans, t);
				continue;
			}
			L l1(p[j], P(dx*200.0, dy*200.0));
			REP(k, n){
				if(1&(i>>k)) continue;
				int b = i | (1<<k);
				if(signum(sp_distance(l1, p[k])) == 0){
					chmin(dp[b][k][dx+10][dy+10], t + abs(p[j]-p[k]));
//					printf("!dq[%d][%d][%d][%d] = (%d, %f)\n", b, k, dx, dy, t.first, t.second + abs(p[j]-p[k]));
					continue;
				}
				if(chmin(dp[b][k][pp[j][k].first+10][pp[j][k].second+10], t + 1000 + abs(p[j]-p[k]))){
//					printf("dq[%d][%d][%d][%d] = (%d, %f)\n", b, k, (int)dir.X/g, (int)dir.Y/g, t.first+1, t.second + abs(p[j]-p[k]));
				}
				REP(l, n){
					if(1&(b>>l)) continue;
					L l2(p[k], (p[k]-p[l])*200.0);
					if(!ss_intersects(l1, l2)) continue;
					P is = line_cross(l1, l2);
					chmin(dp[b][k][pp[k][l].first+10][pp[k][l].second+10], t + 1000 + abs(p[j]-is) + abs(is-p[k]));
//					if(chmin(dp[b][k][(int)dir.X/g+10][(int)dir.Y/g+10], pid(t.first + 1, t.second + abs(p[j]-is) + abs(is-p[k]))) && t.second + abs(p[j]-is) + abs(is-p[k]) < 18.48683298)
//						printf("dq[%d][%d][%d][%d] = (%d, %f)\n", b, k, (int)dir.X/g, (int)dir.Y/g, t.first + 1, t.second + abs(p[j]-is) + abs(is-p[k]));
				}
			}
		}
		int t = (int)(ans)/1000;
		printf("%d %.9f\n", t, ans - t*1000);
	}
	return 0;
}
accuracy: 1
time_ms: 1010
memory_kb: 56152
final_rank: 16

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <iterator>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) container.begin(), container.end()
#define RALL(container) container.rbegin(), container.rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
#include <complex>
#include <cmath>
#define EPS 1.0e-10
#define PI 3.1415926535897932384 

// 実数の符号関数
inline int signum(double x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
//XY座標
#define X real()
#define Y imag()
// 点
typedef complex<double> P;
 

// 線分・半直線・直線
struct L { 
	P pos, dir;
	L(){}
	L(P p, P d):pos(p),dir(d){}
};
 
// 多角形
typedef vector<P> G;
 
// 円
struct C { P p; double r; };

// std::norm はabs(p)*abs(p)なので遅い
inline double norm(P p){
	return p.X*p.X+p.Y*p.Y;
}

// 二つのベクトルの内積を計算する
inline double inp(const P& a, const P& b) {
	return (conj(a)*b).real();
}
 
// 二つのベクトルの外積を計算する
inline double outp(const P& a, const P& b) {
	return (conj(a)*b).imag();
}

inline int ccw(const P& p, const P& r, const P& s) {
    P a(r-p), b(s-p);
    int sgn = signum(outp(a, b));
    if (sgn != 0)
        return sgn;
    if (a.real()*b.real() < -EPS || a.imag()*b.imag() < -EPS)
        return -1;
    if (norm(a) < norm(b) - EPS)
        return 1;
    return 0;
}

// ベクトルpをベクトルbに射影したベクトルを計算する
inline P proj(const P& p, const P& b) {
	return b*inp(p,b)/norm(b);
}
 
// 点pから直線lに引いた垂線の足となる点を計算する
inline P perf(const L& l, const P& p) {
	L m(l.pos - p, l.dir);
	return (p + (m.pos - proj(m.pos, m.dir)));
}
 
// 線分sを直線bに射影した線分を計算する
inline L proj(const L& s, const L& b) {
	 return L(perf(b, s.pos), proj(s.dir, b.dir));
}

bool ll_intersects(const L& l, const L& m) {
    return (abs(outp(l.dir, m.dir)) > EPS || abs(outp(l.dir, m.pos-l.pos)) < EPS);
}
P line_cross(const L& l, const L& m) {
    double num = outp(m.dir, m.pos-l.pos);
    double denom = outp(m.dir, l.dir);
    return P(l.pos + l.dir*num/denom);
}
bool ls_intersects(const L& l, const L& s) {
    return (signum(outp(l.dir, s.pos-l.pos)) *
            signum(outp(l.dir, s.pos+s.dir-l.pos)) <= 0);
}
bool sp_intersects(const L& s, const P& p) {
    return ( abs(s.pos - p) + abs(s.pos + s.dir - p) - abs(s.dir) < EPS );
}
bool ss_intersects(const L& s, const L& t) {
    return (ccw(s.pos, s.pos+s.dir, t.pos) *
            ccw(s.pos, s.pos+s.dir, t.pos+t.dir) <= 0 &&
            ccw(t.pos, t.pos+t.dir, s.pos) *
            ccw(t.pos, t.pos+t.dir, s.pos+s.dir) <= 0);
}
double lp_distance(const L& l, const P& p) {
    return abs(outp(l.dir, p-l.pos) / abs(l.dir));
}
double ll_distance(const L& l, const L& m) {
    return (ll_intersects(l, m) ? 0 : lp_distance(l, m.pos));
}
double ls_distance(const L& l, const L& s) {
    if (ls_intersects(l, s))
        return 0;
    return min(lp_distance(l, s.pos), lp_distance(l, s.pos+s.dir));
}
double sp_distance(const L& s, const P& p) {
    const P r = perf(s, p);
    const double pos = ((r-s.pos)/s.dir).real();
    if (-EPS <= pos && pos <= 1 + EPS)
        return norm(r - p);
    return min(norm(s.pos - p),
               norm(s.pos+s.dir - p));
}
double ss_distance(const L& s, const L& t) {
    if (ss_intersects(s, t))
        return 0;
    return (max(sp_distance(s, t.pos), max(sp_distance(s, t.pos+t.dir), max(sp_distance(t, s.pos), sp_distance(t, s.pos+s.dir)))));
}


const int INF = 1<<28;
const int MOD = 1000000007;


int n;

double dp[1<<10][11][25][25];
main(){
	int i,j;
	while(cin >> n, n){
		REP(i, 1<<n)REP(j, n)REP(k, 22)REP(l, 22) dp[i][j][k][l] = 10000;
		double ans(10000);
		vector<P> p(n);
		REP(i, n){
			double x, y;
			cin >> x >> y;
			p[i] = P(x, y);
		}
		vector<pii> dr;
		REP(i, n)REP(j, i){
			P dir = p[i]-p[j];
			int g = __gcd((int)abs(dir.X), (int)abs(dir.Y));
			dr.emplace_back((int)dir.X/g, (int)dir.Y/g);
			dr.emplace_back(-(int)dir.X/g, (int)dir.Y/g);
			dr.emplace_back((int)dir.X/g, -(int)dir.Y/g);
			dr.emplace_back(-(int)dir.X/g, -(int)dir.Y/g);
		}
		sort(ALL(dr));
		UNIQUE(dr);
		REP(i, 1<<n)REP(j, n)REP(d, dr.size()){
			int dx = dr[d].first;
			int dy = dr[d].second;
			double &t = dp[i][j][dx+10][dy+10];
			
			if(i == (1<<j)) t = .0;
			if(t > 9000) continue;
//			printf("dp[%d][%d][%d][%d] = (%d, %f)\n", i, j, dx, dy, t.first, t.second);
			if(i == (1<<n)-1){
				ans = min(ans, t);
				continue;
			}
			L l1(p[j], P(dx*200.0, dy*200.0));
			REP(k, n){
				if(1&(i>>k)) continue;
				int b = i | (1<<k);
				if(signum(sp_distance(l1, p[k])) == 0){
					chmin(dp[b][k][dx+10][dy+10], t + abs(p[j]-p[k]));
//					printf("!dq[%d][%d][%d][%d] = (%d, %f)\n", b, k, dx, dy, t.first, t.second + abs(p[j]-p[k]));
					continue;
				}
				P dir = p[k] - p[j];
				int g = __gcd((int)abs(dir.X), (int)abs(dir.Y));
				if(chmin(dp[b][k][(int)dir.X/g+10][(int)dir.Y/g+10], t + 1000 + abs(p[j]-p[k]))){
//					printf("dq[%d][%d][%d][%d] = (%d, %f)\n", b, k, (int)dir.X/g, (int)dir.Y/g, t.first+1, t.second + abs(p[j]-p[k]));
				}
				REP(l, n){
					if(1&(b>>l)) continue;
					L l2(p[k], (p[k]-p[l])*200.0);
					if(!ss_intersects(l1, l2)) continue;
					P is = line_cross(l1, l2);
					P dir = p[l] - p[k];
					int g = __gcd((int)(abs(dir.X)+EPS), (int)(abs(dir.Y)+EPS));
					chmin(dp[b][k][(int)dir.X/g+10][(int)dir.Y/g+10], t + 1000 + abs(p[j]-is) + abs(is-p[k]));
//					if(chmin(dp[b][k][(int)dir.X/g+10][(int)dir.Y/g+10], pid(t.first + 1, t.second + abs(p[j]-is) + abs(is-p[k]))) && t.second + abs(p[j]-is) + abs(is-p[k]) < 18.48683298)
//						printf("dq[%d][%d][%d][%d] = (%d, %f)\n", b, k, (int)dir.X/g, (int)dir.Y/g, t.first + 1, t.second + abs(p[j]-is) + abs(is-p[k]));
				}
			}
		}
		int t = (int)(ans)/1000;
		printf("%d %.9f\n", t, ans - t*1000);
	}
	return 0;
}
accuracy: 1
time_ms: 1120
memory_kb: 56156
final_rank: 17

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <iterator>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) container.begin(), container.end()
#define RALL(container) container.rbegin(), container.rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
#include <complex>
#include <cmath>
#define EPS 1.0e-10
#define PI 3.1415926535897932384 

// 実数の符号関数
inline int signum(double x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
//XY座標
#define X real()
#define Y imag()
// 点
typedef complex<double> P;
 

// 線分・半直線・直線
struct L { 
	P pos, dir;
	L(){}
	L(P p, P d):pos(p),dir(d){}
};
 
// 多角形
typedef vector<P> G;
 
// 円
struct C { P p; double r; };

// std::norm はabs(p)*abs(p)なので遅い
inline double norm(P p){
	return p.X*p.X+p.Y*p.Y;
}

// 二つのベクトルの内積を計算する
inline double inp(const P& a, const P& b) {
	return (conj(a)*b).real();
}
 
// 二つのベクトルの外積を計算する
inline double outp(const P& a, const P& b) {
	return (conj(a)*b).imag();
}

inline int ccw(const P& p, const P& r, const P& s) {
    P a(r-p), b(s-p);
    int sgn = signum(outp(a, b));
    if (sgn != 0)
        return sgn;
    if (a.real()*b.real() < -EPS || a.imag()*b.imag() < -EPS)
        return -1;
    if (norm(a) < norm(b) - EPS)
        return 1;
    return 0;
}

// ベクトルpをベクトルbに射影したベクトルを計算する
inline P proj(const P& p, const P& b) {
	return b*inp(p,b)/norm(b);
}
 
// 点pから直線lに引いた垂線の足となる点を計算する
inline P perf(const L& l, const P& p) {
	L m(l.pos - p, l.dir);
	return (p + (m.pos - proj(m.pos, m.dir)));
}
 
// 線分sを直線bに射影した線分を計算する
inline L proj(const L& s, const L& b) {
	 return L(perf(b, s.pos), proj(s.dir, b.dir));
}

bool ll_intersects(const L& l, const L& m) {
    return (abs(outp(l.dir, m.dir)) > EPS || abs(outp(l.dir, m.pos-l.pos)) < EPS);
}
P line_cross(const L& l, const L& m) {
    double num = outp(m.dir, m.pos-l.pos);
    double denom = outp(m.dir, l.dir);
    return P(l.pos + l.dir*num/denom);
}
bool ls_intersects(const L& l, const L& s) {
    return (signum(outp(l.dir, s.pos-l.pos)) *
            signum(outp(l.dir, s.pos+s.dir-l.pos)) <= 0);
}
bool sp_intersects(const L& s, const P& p) {
    return ( abs(s.pos - p) + abs(s.pos + s.dir - p) - abs(s.dir) < EPS );
}
bool ss_intersects(const L& s, const L& t) {
    return (ccw(s.pos, s.pos+s.dir, t.pos) *
            ccw(s.pos, s.pos+s.dir, t.pos+t.dir) <= 0 &&
            ccw(t.pos, t.pos+t.dir, s.pos) *
            ccw(t.pos, t.pos+t.dir, s.pos+s.dir) <= 0);
}
double lp_distance(const L& l, const P& p) {
    return abs(outp(l.dir, p-l.pos) / abs(l.dir));
}
double ll_distance(const L& l, const L& m) {
    return (ll_intersects(l, m) ? 0 : lp_distance(l, m.pos));
}
double ls_distance(const L& l, const L& s) {
    if (ls_intersects(l, s))
        return 0;
    return min(lp_distance(l, s.pos), lp_distance(l, s.pos+s.dir));
}
double sp_distance(const L& s, const P& p) {
    const P r = perf(s, p);
    const double pos = ((r-s.pos)/s.dir).real();
    if (-EPS <= pos && pos <= 1 + EPS)
        return norm(r - p);
    return min(norm(s.pos - p),
               norm(s.pos+s.dir - p));
}
double ss_distance(const L& s, const L& t) {
    if (ss_intersects(s, t))
        return 0;
    return (max(sp_distance(s, t.pos), max(sp_distance(s, t.pos+t.dir), max(sp_distance(t, s.pos), sp_distance(t, s.pos+s.dir)))));
}


const int INF = 1<<28;
const int MOD = 1000000007;


int n;

double dp[1<<10][11][25][25];
main(){
	int i,j;
	while(cin >> n, n){
		REP(i, 1<<n)REP(j, n)REP(k, 22)REP(l, 22) dp[i][j][k][l] = 10000;
		double ans(10000);
		vector<P> p(n);
		REP(i, n){
			double x, y;
			cin >> x >> y;
			p[i] = P(x, y);
		}
		vector<pii> dr;
		REP(i, n)REP(j, i){
			P dir = p[i]-p[j];
			int g = __gcd((int)abs(dir.X), (int)abs(dir.Y));
			dr.emplace_back((int)dir.X/g, (int)dir.Y/g);
			dr.emplace_back(-(int)dir.X/g, (int)dir.Y/g);
			dr.emplace_back((int)dir.X/g, -(int)dir.Y/g);
			dr.emplace_back(-(int)dir.X/g, -(int)dir.Y/g);
		}
		REP(i, 1<<n)REP(j, n)REP(d, dr.size()){
			int dx = dr[d].first;
			int dy = dr[d].second;
			double &t = dp[i][j][dx+10][dy+10];
			
			if(i == (1<<j)) t = .0;
			if(t > 9000) continue;
//			printf("dp[%d][%d][%d][%d] = (%d, %f)\n", i, j, dx, dy, t.first, t.second);
			if(i == (1<<n)-1){
				ans = min(ans, t);
				continue;
			}
			L l1(p[j], P(dx*200.0, dy*200.0));
			REP(k, n){
				if(1&(i>>k)) continue;
				int b = i | (1<<k);
				if(signum(sp_distance(l1, p[k])) == 0){
					chmin(dp[b][k][dx+10][dy+10], t + abs(p[j]-p[k]));
//					printf("!dq[%d][%d][%d][%d] = (%d, %f)\n", b, k, dx, dy, t.first, t.second + abs(p[j]-p[k]));
					continue;
				}
				P dir = p[k] - p[j];
				int g = __gcd((int)abs(dir.X), (int)abs(dir.Y));
				if(chmin(dp[b][k][(int)dir.X/g+10][(int)dir.Y/g+10], t + 1000 + abs(p[j]-p[k]))){
//					printf("dq[%d][%d][%d][%d] = (%d, %f)\n", b, k, (int)dir.X/g, (int)dir.Y/g, t.first+1, t.second + abs(p[j]-p[k]));
				}
				REP(l, n){
					if(1&(b>>l)) continue;
					L l2(p[k], (p[k]-p[l])*200.0);
					if(!ss_intersects(l1, l2)) continue;
					P is = line_cross(l1, l2);
					P dir = p[l] - p[k];
					int g = __gcd((int)(abs(dir.X)+EPS), (int)(abs(dir.Y)+EPS));
					chmin(dp[b][k][(int)dir.X/g+10][(int)dir.Y/g+10], t + 1000 + abs(p[j]-is) + abs(is-p[k]));
//					if(chmin(dp[b][k][(int)dir.X/g+10][(int)dir.Y/g+10], pid(t.first + 1, t.second + abs(p[j]-is) + abs(is-p[k]))) && t.second + abs(p[j]-is) + abs(is-p[k]) < 18.48683298)
//						printf("dq[%d][%d][%d][%d] = (%d, %f)\n", b, k, (int)dir.X/g, (int)dir.Y/g, t.first + 1, t.second + abs(p[j]-is) + abs(is-p[k]));
				}
			}
		}
		int t = (int)(ans)/1000;
		printf("%d %.9f\n", t, ans - t*1000);
	}
	return 0;
}
accuracy: 1
time_ms: 4200
memory_kb: 56172
final_rank: 20

code_snippet: #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;

struct point_t {
	double x, y;
	point_t() { x = y = 0; }
	point_t(double tx, double ty) { x = tx, y = ty; }
	point_t operator+(const point_t &r) const {
		return point_t(x + r.x, y + r.y);
	}
	point_t operator-(const point_t &r) const {
		return point_t(x - r.x, y - r.y);
	}
	point_t operator*(const double &r) const {
		return point_t(x * r, y * r);
	}
	point_t operator/(const double &r) const {
		return point_t(x / r, y / r);
	}
	double l() const {
		return sqrt(x * x + y * y);
	}
	void read() { scanf("%lf%lf", &x, &y); }
};

const double eps = 1e-8;
int dblcmp(double x) {
	return x < -eps ? -1 : x > eps;
}

double dot(point_t p1, point_t p2) {
	return p1.x * p2.x + p1.y * p2.y;
}

double cross(point_t p1, point_t p2) {
	return p1.x * p2.y - p1.y * p2.x;
}

bool onseg(point_t p1, point_t p2, point_t p) {
	if (dblcmp(cross(p - p1, p2 - p1)) != 0) return false;
	return dblcmp(dot(p1 - p, p2 - p)) <= 0;
}

double dist(point_t p1, point_t p2) {
	p2 = p2 - p1;
	return p2.l();
}

const int maxn = 11;
int n, final;
point_t p[maxn];
int kill[maxn][maxn];

point_t isLL(point_t a, point_t b, point_t c, point_t d, bool &parell) {
	point_t p1 = b - a, p2 = d - c;
	double a1 = p1.y, b1 = -p1.x, c1;
	double a2 = p2.y, b2 = -p2.x, c2;
	if (dblcmp(a1 * b2 - a2 * b1) == 0) {
		parell = true;
		return point_t();
	} else {
		parell = false;
		c1 = a1 * a.x + b1 * a.y;
		c2 = a2 * c.x + b2 * c.y;
		return point_t((c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1), (c1 * a2 - c2 * a1) / (b1 * a2 - b2 * a1));
	}
}

double getscale(point_t v1, point_t v2) {
	if (dblcmp(v1.y) == 0) return v2.x / v1.x;
	return v2.y / v1.y;
}

pair<int, double> dp[maxn][maxn][1 << maxn];

void work() {
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			for (int mask = 0; mask <= final; ++mask) {
				dp[i][j][mask].first = 100;
			}
		}
	}
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			dp[i][j][kill[i][j]] = make_pair(0, dist(p[i], p[j]));
		}
	}
	for (int mask = 0; mask <= final; ++mask) {
		for (int v = 1; v <= n; ++v) {
			for (int u = 1; u <= n; ++u) {
				if (dp[u][v][mask].first == 100) continue;
				point_t dir = p[u] - p[v];
				for (int i = 1; i <= n; ++i) {
					for (int j = 1; j <= n; ++j) {
						if (i == j) continue;
						bool parell = false;
						point_t is = isLL(p[u], p[u] + dir, p[i], p[j], parell);
						if (parell) continue;
						double len2 = dp[u][v][mask].second;
						double s1 = getscale(dir, is - p[u]);
						double s2 = getscale(p[j] - p[i], is - p[i]);
						if (dblcmp(s1) < 0 || dblcmp(s2 - 1) < 0) continue;
						len2 += dist(is, p[u]);
						len2 += dist(p[i], is);
						pair<int, double> &bind = dp[i][j][mask | kill[i][j]];
						bind = min(bind, make_pair(dp[u][v][mask].first + 1, len2));	
					}
				}
			}
		}
	}
}

int main() {
	while (scanf("%d", &n) != EOF) {
		if (n == 0) break;
		final = (1 << n) - 1;
		for (int i = 1; i <= n; ++i) p[i].read();
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				int mask = 0;
				for (int k = 1; k <= n; ++k) {
					if (onseg(p[i], p[j], p[k])) mask |= (1 << (k - 1));
				}
				kill[i][j] = mask;
			}
		}
		work();
		pair<int, double> ans = make_pair(100, 0);
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				if (i == j) continue;
				ans = min(ans, dp[i][j][final]);
			}
		}
		printf("%d %.10lf\n", ans.first, ans.second);
	}
	return 0;
}
accuracy: 1
time_ms: 1180
memory_kb: 5120
final_rank: 5