#include <algorithm>/*{{{*/
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#define FOR(i, b, e) for (typeof(b) i = (b); assert((i) <= (e)), i != (e); ++i)
#define SZ(a) ((int)a.size())
#define PB(e) push_back(e)
#define SORT(v) sort((v).begin(), (v).end())
#define RSORT(v) sort((v).rbegin(),(v).rend())
#define F first
#define S second
#define MP(a, b) make_pair(a, b)
#define BIT(n) (1ULL << (n))
#define RANGE(a, b, c) ((a) <= (b) && (b) <= (c))

static const double PI (3.14159265358979323846);
static const double EPS (1e-10);

using namespace std;
typedef long long int LL;
/*}}}*/

typedef complex<double> P;

// 許容する誤差ε
#define EPS (1e-10)
// 2つのスカラーが等しいかどうか
#define EQ(a,b) (abs((a)-(b)) < EPS)
// 2つのベクトルが等しいかどうか
#define EQV(a,b) ( EQ((a).real(), (b).real()) && EQ((a).imag(), (b).imag()) )


// 内積 (dot product) : a・b = |a||b|cosΘ
double dot(P a, P b) {
  return (a.real() * b.real() + a.imag() * b.imag());
}

// 外積 (cross product) : a×b = |a||b|sinΘ
double cross(P a, P b) {
  return (a.real() * b.imag() - a.imag() * b.real());
}

// 2直線の直交判定 : a⊥b <=> dot(a, b) = 0
int is_orthogonal(P a1, P a2, P b1, P b2) {
  return EQ( dot(a1-a2, b1-b2), 0.0 );
}

// 2直線の平行判定 : a//b <=> cross(a, b) = 0
int is_parallel(P a1, P a2, P b1, P b2) {
  return EQ( cross(a1-a2, b1-b2), 0.0 );
}

// 点cが直線a,b上にあるかないか
int is_point_on_line(P a, P b, P c) {
  return EQ( cross(b-a, c-a), 0.0 );
}

// 点cが線分a,b上にあるかないか(1)
//int is_point_on_line(P a, P b, P c) {
//  return EQ( cross(b-a, c-a), 0.0 ) &&
//         (dot(b-a, c-a) > -EPS) &&
//         (dot(a-b, c-b) > -EPS);
//}

// 点cが線分a,b上にあるかないか(2)
//int is_point_on_line(P a, P b, P c) {
//  // |a-c| + |c-b| <= |a-b| なら線分上
//  return (abs(a-c) + abs(c-b) < abs(a-b) + EPS);
//}

// 点a,bを通る直線と点cとの距離
double distance_l_p(P a, P b, P c) {
  return abs(cross(b-a, c-a)) / abs(b-a);
}

// 点a,bを端点とする線分と点cとの距離
double distance_ls_p(P a, P b, P c) {
  if ( dot(b-a, c-a) < EPS ) return abs(c-a);
  if ( dot(a-b, c-b) < EPS ) return abs(c-b);
  return abs(cross(b-a, c-a)) / abs(b-a);
}

// a1,a2を端点とする線分とb1,b2を端点とする線分の交差判定
int is_intersected_ls(P a1, P a2, P b1, P b2) {
  return ( cross(a2-a1, b1-a1) * cross(a2-a1, b2-a1) < EPS ) &&
         ( cross(b2-b1, a1-b1) * cross(b2-b1, a2-b1) < EPS );
}

// a1,a2を端点とする線分とb1,b2を端点とする線分の交点計算
P intersection_ls(P a1, P a2, P b1, P b2) {
  P b = b2-b1;
  double d1 = abs(cross(b, a1-b1));
  double d2 = abs(cross(b, a2-b1));
  double t = d1 / (d1 + d2);

  return a1 + (a2-a1) * t;
}

// a1,a2を通る直線とb1,b2を通る直線の交差判定
int is_intersected_l(P a1, P a2, P b1, P b2) {
  return !EQ( cross(a1-a2, b1-b2), 0.0 );
}

// a1,a2を通る直線とb1,b2を通る直線の交点計算
P intersection_l(P a1, P a2, P b1, P b2) {
  P a = a2 - a1; P b = b2 - b1;
  return a1 + a * cross(b, b1-a1) / cross(b, a);
}

struct line_seg {
	P start;
	P end;
};

struct star {
	line_seg lines[5];
};
vector<star> stars;

#define INF (INT_MAX - 1)
#define MAX_N 100
double dist[MAX_N][MAX_N];

int main(int argc, char const* argv[])
{
	int N, M, L;
	while (cin >> N >> M >> L, N || M || L) {
		FOR(i, 0, N) {
			double x, y, a, r;
			cin >> x >> y >> a >> r;
			a = a * 2 * PI / 360.0;

			star s;
			P vertex;
			vertex.real() = r * cos(PI/2.0 + a);
			vertex.imag() = r * sin(PI/2.0 + a);
			FOR(j, 1, 6) {
				line_seg ls;
				ls.start.real() = vertex.real() + x;
				ls.start.imag() = vertex.imag() + y;

				double rot = a + j * (72 * 2 * 2 * PI / 360.0);
				vertex.real() = r * cos(PI/2.0 + rot);
				vertex.imag() = r * sin(PI/2.0 + rot);

				ls.end.real() = vertex.real() + x;
				ls.end.imag() = vertex.imag() + y;

				s.lines[j-1] = ls;
			}
			stars.PB(s);
		}

		// debug
		FOR(i, 0, SZ(stars)) {
			printf("star %d\n", i);
			FOR(j, 0, 5) {
				printf("(%lf, %lf)-(%lf, %lf)\n", stars[i].lines[j].start.real(), stars[i].lines[j].start.imag(), stars[i].lines[j].end.real(), stars[i].lines[j].end.imag());
			}
		}

		FOR(i, 0, SZ(stars)) {
			FOR(j, 0, SZ(stars)) {
				if (i == j) {
					dist[i][j] = 0;
					continue;
				}

				double min_dist = INF;
				FOR(k, 0, 5) {
					FOR(l, 0, 5) {
						double tmp = min(
								min( distance_ls_p(stars[i].lines[k].start, stars[i].lines[k].end, stars[j].lines[l].start),
										distance_ls_p(stars[i].lines[k].start, stars[i].lines[k].end, stars[j].lines[l].end) ),
								min( distance_ls_p(stars[j].lines[l].start, stars[j].lines[l].end, stars[i].lines[k].start),
										distance_ls_p(stars[j].lines[l].start, stars[j].lines[l].end, stars[i].lines[k].end) )
								);
						min_dist = min(min_dist, tmp);
					}
				}
				dist[i][j] = dist[j][i] = min_dist;
				printf("distance between (%d) and (%d) = %lf\n", i, j, min_dist);
			}
		}

		FOR(k, 0, N) {
			FOR(i, 0, N) {
				FOR(j, 0, N) {
					dist[i][j] = min( dist[i][j], dist[i][k] + dist[k][j] );
				}
			}
		}
		cout << dist[M-1][L-1] << endl;
	}
	return 0;
}