#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <climits>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1<<29;
const double PI = acos(-1);
const double EPS = 1e-8;

typedef complex<double> P;
namespace std {
  bool operator < (const P& a, const P& b) {
    if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() {}
};
typedef vector<P> G;
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]


int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > 0)   return +1;       // counter clockwise
  if (cross(b, c) < 0)   return -1;       // clockwise
  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;
}
P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

G convex_cut(const G& g, const L& l) {
  G Q;
  REP(i, g.size()) {
    P A = curr(g, i), B = next(g, i);
    if (ccw(l[0], l[1], A) != -1) Q.push_back(A);
    if (ccw(l[0], l[1], A)*ccw(l[0], l[1], B) < 0)
      Q.push_back(crosspoint(L(A, B), l));
  }
  return Q;
}
// 垂直二等分線
L bisector(const P &a, const P &b) {
  P A = (a+b)*P(0.5,0);
  return L(A, A+(b-a)*P(0, PI/2));
}
// ボロノイ領域
G voronoi_cell(G g, const vector<P> &v, int s) {
  REP(i, v.size())
    if (i!=s)
      g = convex_cut(g, bisector(v[s], v[i]));
  return g;
}
bool ok(const P &p) {
  return -EPS < p.imag() && p.imag() < 4+EPS;
}
double adj[500][500];
int main() {
  int n;
  while(cin>>n, n) {
    REP(i,500)REP(j,500) adj[i][j] = INF;
    G g;
    g.push_back(P(0,-1));
    g.push_back(P(4,-1));
    g.push_back(P(4,5));
    g.push_back(P(0,5));
    vector<P> v(n);
    REP(i,n) cin>>v[i].real()>>v[i].imag();
    map<P, int> mp;
    int num = 0;
    set<int> start, end;
    REP(i,n) {
      G vo = voronoi_cell(g, v, i);
      FOR(it, vo) {
        if (ok(*it)) {
          if (mp.count(*it) == 0) {
            mp[*it] = num++;
          }
          if (it->real()<EPS) start.insert(mp[*it]);
          if (it->real()>4-EPS) end.insert(mp[*it]);
        }
      }
      REP(j, vo.size()-1) {
        if (ok(vo[j]) && ok(vo[j+1])) {
          int a = mp[vo[j]], b = mp[vo[j+1]];
          adj[b][a] = adj[a][b] = abs(vo[j]-vo[j+1]);
        }
      }
    }
    // FOR(it, mp) cout << it->first << " " << it->second << endl;
    // REP(i,num){REP(j,num)cout<<adj[i][j]<< " ";cout<<endl;}
    
    REP(k,num) REP(i,num) REP(j,num)
      adj[i][j] = min(adj[i][j], adj[i][k]+adj[k][j]);
    
    double ans = INF;
    FOR(it, start) {
      FOR(jt, end) {
        ans = min(ans, adj[*it][*jt]);
      }
    }
    if (ans > INF-1) {
      cout << "impossible" << endl;
    } else {
      printf("%.8f\n", ans);
    }
  }
}

Measured memory_bytes: 0