#include <bits/stdc++.h>
using namespace std;
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T>
inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
const double EPS = 1e-10;
const double PI = acos(-1.0);
double x[100], y[100], a[100], r[100];
double toRad(int deg) { return (double)deg * 2 * PI / 360; }
complex<double> getCoord(int i, int j) {
  double xx = x[i] + r[i] * cos(toRad(90 + a[i] + 72 * j));
  double yy = y[i] + r[i] * sin(toRad(90 + a[i] + 72 * j));
  return complex<double>(xx, yy);
}
double getDist(const complex<double> &left, const complex<double> &right) {
  return sqrt(pow(left.real() - right.real(), 2) +
              pow(left.imag() - right.imag(), 2));
}
struct node {
  int n;
  double cost;
  node(int n, double cost) : n(n), cost(cost) {}
  bool operator<(const node &other) const { return cost > other.cost; }
};
const int MAX = INT_MAX / 10;
double cross(complex<double> a, complex<double> b) {
  return (a.real() * b.imag() - a.imag() * b.real());
}
bool crossing(complex<double> a1, complex<double> a2, complex<double> b1,
              complex<double> b2) {
  if ((abs((cross(a1 - a2, b1 - b2)) - (0.0)) < EPS)) return false;
  return (cross(a2 - a1, b1 - a1) * cross(a2 - a1, b2 - a1) < EPS) &&
         (cross(b2 - b1, a1 - b1) * cross(b2 - b1, a2 - b1) < EPS);
}
int main() {
  int N, M, L;
  while (cin >> N >> M >> L, N) {
    for (int i = (0); i < (N); ++i) {
      cin >> x[i] >> y[i] >> a[i] >> r[i];
    }
    vector<vector<double> > dist(N, vector<double>(N, MAX));
    for (int i = (0); i < (N); ++i) {
      for (int j = (0); j < (5); ++j) {
        for (int k = (0); k < (N); ++k) {
          bool flag = false;
          for (int l = (0); l < (5); ++l) {
            complex<double> left = getCoord(i, j);
            complex<double> left2 = getCoord(i, (j + 2) % 5);
            complex<double> right = getCoord(k, l);
            complex<double> right2 = getCoord(k, (l + 2) % 5);
            if (crossing(left, left2, right, right2)) {
              flag = true;
              dist[i][k] = 0;
            }
            if (!flag) {
              dist[i][k] = min(dist[i][k], getDist(left, right));
            }
          }
        }
      }
    }
    vector<double> cost(N, MAX);
    priority_queue<node> q;
    for (int i = (0); i < (5); ++i) {
      q.push(node(M - 1, 0));
      cost[M - 1] = 0;
    }
    while (!q.empty()) {
      node n = q.top();
      q.pop();
      if (n.cost > cost[n.n]) continue;
      for (int i = (0); i < (N); ++i) {
        if (dist[n.n][i] < MAX) {
          double dd = cost[n.n] + dist[n.n][i];
          if (cost[i] > dd) {
            cost[i] = dd;
            q.push(node(i, dd));
          }
        }
      }
    }
    printf("%.10f\n", cost[L - 1]);
  }
}
