#include <bits/stdc++.h>

#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)

#define _all(arg) begin(arg),end(arg)
#define uniq(arg) sort(_all(arg)),(arg).erase(unique(_all(arg)),end(arg))

using namespace std;

template<class T>void reg(vector<T> &ary,const T &elem){ary.emplace_back(elem);}
template<class T>bool chmin(T &a, const T &b) {return (b<a)?(a=b,1):0;}

using R=long double;
const R EPS = 1E-10;
const R INF = 1E40;
constexpr R PI = acos(R(-1));
inline int sgn(const R& r){ return (r > EPS) - (r < -EPS);}
inline int sgn(const R& a, const R &b){ return sgn(a-b); }
inline R sq(R x){return sqrt(max<R>(x,0.0));}

using P=complex<R>;
using VP=vector<P>;
using L=struct{P s,t;};
using VL=vector<L>;

constexpr P O = P(0,0);
istream& operator >> (istream& is,P& p){ R x,y;is >> x >> y; p=P(x,y); return is;}

namespace std{
	bool operator <  (const P& a,const P& b){ return sgn(real(a-b))?real(a-b)<0:sgn(imag(a-b))<0;}
	bool operator == (const P& a,const P& b){ return sgn(real(a-b))==0 && sgn(imag(a-b))==0;}
}

inline R dot(P o,P a,P b){a-=o,b-=o; return real(conj(a)*b);}
inline R det(P o,P a,P b){a-=o,b-=o; return imag(conj(a)*b);}

enum CCW{ LEFT = 1,RIGHT = 2,BACK = 4,FRONT = 8,ON = 16};
inline int ccw(P o,P a, P b) {
	if (sgn(det(o,a,b)) > 0) return LEFT;
	if (sgn(det(o,a,b)) < 0) return RIGHT;
	if (sgn(dot(o,a,b)) < 0) return BACK;
	if (sgn(norm(a-o)-norm(b-o)) < 0) return FRONT;
	return ON;
}

bool parallel(L a, L b) {return sgn(det(O,a.t-a.s,b.t-b.s))==0;}
bool eql(L a,L b){ return (parallel(a,b) && sgn(det(a.s,a.t,b.s))==0);}

bool iss(L a,L b,int end=0){
	int s1=ccw(a.s,a.t,b.s)|ccw(a.s,a.t,b.t);
	int s2=ccw(b.s,b.t,a.s)|ccw(b.s,b.t,a.t);
	if(end) return (s1&s2)==(LEFT|RIGHT);
	return (s1|s2)&ON || (s1&s2)==(LEFT|RIGHT);
}

P cross(L a,L b){
	R s1=det(a.s,b.s,b.t);
	R s2=s1+det(a.t,b.t,b.s);
	return a.s+s1/s2*(a.t-a.s);
}
	
VP convex_cut(const VP& pol,const L& l) {
	VP res;
	int n=pol.size();
	rep(i,n){
		P a = pol[i],b=pol[(i+1)%n];
		if(ccw(l.s,l.t,a)!=RIGHT) reg(res,a);
		if((ccw(l.s,l.t,a)|ccw(l.s,l.t,b))==(LEFT|RIGHT)) reg(res,cross({a,b},l));
	}
	return res;
}

const int vmax=5010;
struct node{int to;R cost;};
vector<node> graph[vmax];
inline void add_edge(int f,int t,R c){reg(graph[f],{t,c}),reg(graph[t],{f,c});}

void segment_arrangement(const vector<L> &seg, vector<P> &point){
	rep(i,vmax) graph[i].clear();
	int n=seg.size();
	rep(i,n){
		reg(point,seg[i].s),reg(point,seg[i].t);
		rep(j,i) if(iss(seg[i],seg[j],1)) reg(point,cross(seg[i],seg[j]));
	}
	uniq(point);
	rep(i,n){
		vector<pair<R,int>> idx;
		rep(j,point.size()) if(ccw(seg[i].s,seg[i].t,point[j])==ON) reg(idx,{norm(point[j]-seg[i].s),j});
		sort(_all(idx));
		rep(j,1,int(idx.size())){
			int a=idx[j-1].second,b=idx[j].second;
			add_edge(a,b,abs(point[a]-point[b]));
		}
	}
}

L bisector(P a, P b){P mid=(a+b)/P(2,0);return L{mid, mid+(b-a)*P(0,1)};}
VP voronoi_cell(VP pol,VP v,int s){rep(i,v.size())if(i!=s)pol=convex_cut(pol,bisector(v[s],v[i]));return pol;}

R dist[vmax];
R dijkstra(const VP &point){
	fill(dist,dist+vmax,INF);
	using state=tuple<R,int>;
	priority_queue<state,vector<state>,greater<state>> q;
	rep(s,point.size()) if(sgn(real(point[s]))==0) dist[s]=0,q.push(state(0,s));
	while(!q.empty()){
		R c;int v;
		tie(c,v)=q.top();q.pop();
		for(auto &e:graph[v]){
			R nc=c+e.cost; int nv=e.to;
			if(chmin(dist[nv],nc)) q.push(state(nc,nv));
		}
	}
	R res=INF;
	rep(t,point.size()) if(sgn(real(point[t])-4.0)==0) chmin(res,dist[t]);
	return res;
}

int main(void){
	int n;
	while(cin >> n,n){
		VP pol={P(0,0),P(4,0),P(4,4),P(0,4)};
		VP vornoi,point;
		VL seg;
		rep(i,n){
			P p;
			cin >> p;
			reg(vornoi,p);
		}
		rep(i,n){
			VP res=voronoi_cell(pol,vornoi,i);
			for(auto &p:res) reg(point,p);
			int m=res.size();
			rep(i,m){
				L l={res[i],res[(i+1)%m]};
				bool ok=true;
				rep(i,4) if(eql(l,{pol[i],pol[(i+1)%4]})) ok=false;
				if(ok) reg(seg,l);
			}
		}
		segment_arrangement(seg,point);
		R res=dijkstra(point);
		cout.precision(20);
		if(res>=INF)
			cout << "impossible" << endl;
		else
			cout << fixed << res << endl;
	}
	return 0;
}

Measured memory_bytes: 3508