// ACM-ICPCアジア地区予選2014 H. Cornering at Poles

#include <iostream>
#include <vector>
#include <complex>
#include <queue>
#include <cmath>
#include <cstdio>

using namespace std;

const double EPS = 1e-12;
const double PI = acos(-1);
typedef complex<double> P;
typedef pair<P, double> C;

struct L { P p, q; L(P p, P q) : p(p), q(q) {} };

double dot(P a, P b) { return real(conj(a)*b); }
double cross(P a, P b) { return imag(conj(a)*b); }
double angle(P a, P b) { return arg(conj(a)*b); }

double distSP(L l, P p){
	if(dot(l.q-l.p,p-l.p)<-EPS) return abs(p-l.p);
	if(dot(l.p-l.q,p-l.q)<-EPS) return abs(p-l.q);
	return abs(cross(l.q-l.p,p-l.p))/abs(l.q-l.p);
}

void getCommonTangent(vector<L> &res, C c1, C c2){
	if(c1.second > c2.second) swap(c1, c2);
	P dir = c1.first-c2.first;
	double dist = abs(c1.first-c2.first);
	dir = dir/dist*c2.second;
	if(dist + c1.second < c2.second - EPS) return ;

	for(int sgn=-1;sgn<=1;sgn+=2){
		double cs = (c2.second+sgn*c1.second)/dist;
		P d = P(cs, sqrt(1-cs*cs));
		res.push_back(L(c2.first+dir*d, c2.first+dir*d*P(1,1)));
		if(imag(d) > EPS)
			res.push_back(L(c2.first+dir*conj(d), c2.first+dir*conj(d)*P(1,1)));
		if(dist+EPS < c1.second+c2.second) break;
	}
}

pair<P,P> crossPoint(C c1, C c2){
	double r1 = c1.second;
	double r2 = c2.second;
	double r3 = abs(c1.first-c2.first);
	double rc = (r3*r3+r1*r1-r2*r2)/(2*r3);
	double rs = sqrt(r1*r1-rc*rc);
	P dif = (c2.first-c1.first)/r3;
	P p1 = c1.first+dif*P(rc,rs);
	P p2 = c1.first+dif*P(rc,-rs);
	return make_pair(p1,p2);
}

bool crossCircle(C c1, C c2){
	double r1 = c1.second;
	double r2 = c2.second;
	double d = abs(c1.first-c2.first);
	if(d<r1||d<r2) return d-abs(r1-r2) > EPS;
	return r1+r2-d > -EPS;
}

P ssCrosspoint(L a, L b){
	double A = cross(a.q-a.p, b.q-b.p);
	double B = cross(a.q-a.p, a.q-b.p);
	return b.p + B/A * (b.q-b.p);
}

void getTangent(vector<L>& res, C c, P p){
	double radius = sqrt(norm(p-c.first) - c.second*c.second);
	pair<P,P> pr = crossPoint(c, make_pair(p, radius));
	res.push_back(L(p, pr.first));
	res.push_back(L(p, pr.second));
}

bool overlap(C c1, C c2){
	double d = abs(c1.first-c2.first);
	return c2.second-(d+c1.second) > -EPS;
}

int getIndex(vector<P>& idx, P p){
	int size = idx.size();
	for(int i=0;i<size;++i){
		if(norm(idx[i] - p) < EPS) return i;
	}
	idx.push_back(p);
	return size;
}

bool isValidLine(const L& l, const vector<C>& vc, int idxA, int idxB){
	for(int i=0;i<vc.size();i++){
		if(i==idxA || i==idxB) continue;
		if(distSP(l, vc[i].first) < vc[i].second + EPS) return false;
	}
	return true;
}

void addToGraph(vector< vector< pair<int, double> > >& g, vector<P>& idx, const P& p1, const P& p2){
	int idxA = getIndex(idx, p1);
	int idxB = getIndex(idx, p2);
	double len = abs(p1-p2);
	while(max(idxA, idxB) >= g.size()) g.push_back(vector< pair<int,double> >());
	g[idxA].push_back(make_pair(idxB, len));
	g[idxB].push_back(make_pair(idxA, len));
}

int main(){
	P start(0, 0), goal;
	int N;
	while(cin >> N >> goal.real() >> goal.imag()){
		vector<C> vc;
		for(int i=0;i<N;i++){
			int x, y; cin >> x >> y;
			vc.push_back(make_pair(P(x, y), 100));
		}

		vector< vector<P> > crossP(vc.size());
		for(int i=0;i<vc.size();i++){
			for(int j=i+1;j<vc.size();j++){
				if(crossCircle(vc[i], vc[j])){
					pair<P, P> res = crossPoint(vc[i], vc[j]);
					crossP[i].push_back(res.first);
					crossP[i].push_back(res.second);
					crossP[j].push_back(res.first);
					crossP[j].push_back(res.second);
				}
			}
		}

		vector< vector< pair<int, double> > > g;
		vector<P> idx;
		{
			L l = L(start, goal);
			bool ok = true;
			for(int i=0;i<vc.size();i++){
				if(distSP(l, vc[i].first) < vc[i].second + EPS) ok = false;
			}
			if(ok){
				addToGraph(g, idx, start, goal);
			}
		}
		for(int i=0;i<vc.size();i++){
			vector<L> vlS;
			getTangent(vlS, vc[i], start);
			getTangent(vlS, vc[i], goal);
			for(int k=0;k<vlS.size();k++){
				if(!isValidLine(vlS[k], vc, i, -1)) continue;
				addToGraph(g, idx, vlS[k].p, vlS[k].q);
			}

			for(int j=i+1;j<vc.size();j++){
				if(overlap(vc[i], vc[j]) || overlap(vc[j], vc[i])) continue;
				vector<L> vl;
				getCommonTangent(vl, vc[i], vc[j]);
				for(int k=0;k<vl.size();k++){
					P dir = P(0, 1)*(vl[k].q - vl[k].p);
					P ta = ssCrosspoint(L(vc[i].first, vc[i].first+dir), vl[k]);
					P tb = ssCrosspoint(L(vc[j].first, vc[j].first+dir), vl[k]);

					if(!isValidLine(L(ta, tb), vc, i, j)) continue;
					addToGraph(g, idx, ta, tb);
				}
			}
		}

		for(int i=0;i<vc.size();i++){
			vector<int> mem;
			for(int j=0;j<idx.size();j++){
				if(abs(abs(idx[j]-vc[i].first)-vc[i].second) < EPS){
					mem.push_back(j);
				}
			}
			for(int j=0;j<mem.size();j++){
				for(int k=j+1;k<mem.size();k++){
					double agl = angle(idx[mem[j]]-vc[i].first, idx[mem[k]]-vc[i].first);
					P base = (agl > 0 ? idx[mem[j]] : idx[mem[k]]);
					agl = abs(agl);
					bool ok = true;
					for(int b=0;b<crossP[i].size();b++){
						double aglB = angle(base-vc[i].first, crossP[i][b]-vc[i].first);
						if(-EPS < aglB && aglB < agl+EPS) ok = false;
					}
					if(ok){
						g[mem[j]].push_back(make_pair(mem[k], agl*vc[i].second));
						g[mem[k]].push_back(make_pair(mem[j], agl*vc[i].second));
					}
				}
			}
		}
		int idxS = getIndex(idx, start);
		int idxG = getIndex(idx, goal);

		priority_queue< pair<double, int> > qu; qu.push(make_pair(0, idxS));
		vector<int> visit(idx.size(), 0);
		vector<double> dist(idx.size(), 1e12);
		dist[idxS] = 0;
		while(!qu.empty()){
			pair<double, int> pr = qu.top(); qu.pop();
			double d = -pr.first; int pos = pr.second;
			if(visit[pos]) continue;
			visit[pos] = 1;
			if(g.size() <= pos) continue;
			for(int i=0;i<g[pos].size();i++){
				int next = g[pos][i].first;
				if(visit[next]) continue;
				double ndist = dist[pos] + g[pos][i].second;
				if(dist[next] > ndist){
					dist[next] = ndist;
					qu.push(make_pair(-ndist, next));
				}
			}
		}
		if(!visit[idxG]) printf("0.0\n");
		else             printf("%.10lf\n", dist[idxG]);
	}
}

Measured memory_bytes: 1508