#include <cstdio>
#include <cstring>
#include <cassert>
#include <vector>
#include <queue>
#include <complex>
#include <algorithm>
using namespace std;

#define EQ(x, y) (abs((x)-(y)) < EPS)
#define EPS 1e-8
#define INF 0x33433433

#define X real()
#define Y imag()

//typedef float double;
typedef pair<int, int> Pair;
typedef complex<double> Point;
typedef Point Vec;

namespace std {
  bool operator<(Point a, Point b) {
    if (a.X != b.X) return a.X < b.X;
    return a.Y < b.Y;
  }
}

class Line : public vector<Point> {
public:
  Line () {resize(2);}
  Line (Point a, Point b) {
    push_back(a);
    push_back(b);
  }
};

struct Circle {
  Point c;
  double r;
};

double dot(Point a, Point b) {
  return (conj(a)*b).X;
}

double cross(Point a, Point b) {
  return (conj(a)*b).Y;
}

int ccw(Point a, Point b, Point c) {
  b -= a;
  c -= a;
  if (cross(b, c) > 0) return 1;
  if (cross(b, c) < 0) return -1;
  if (dot(b, c) < 0) return 2;
  if (norm(b) < norm(c)) return -2;
  return 0;
}

Point proj(Line l, Point p) {
  Point v = l[1]-l[0];
  double ratio = dot(v, p-l[0]) / norm(v);
  return l[0] + ratio*v;
}

double DistLP(Line l, Point p) {
  return abs(p - proj(l, p));
}

vector<Point> CrossPointCL(Circle c, Line l){
  vector<Point> ret;
  double d = DistLP(l, c.c);
  if(d < c.r + EPS){
    double ratio = (d > c.r) ? 0.0 : sqrt(c.r*c.r - d*d);
    Point sgn = (l[0] - l[1]) / abs(l[0] - l[1]);
    ret.push_back(proj(l, c.c) + ratio * sgn);
    ret.push_back(proj(l, c.c) - ratio * sgn);
  }

  return ret;
}

vector<Point> CrossPointCC(Circle c1, Circle c2){
  vector<Point> ret;
  double d = abs(c1.c - c2.c);
  double rc = (d*d + c1.r*c1.r - c2.r*c2.r) / (2*d);
  double dfr = c1.r*c1.r - rc*rc;

  if (EQ(dfr, 0.0)) dfr = 0.0;
  else if(dfr < 0.0) return ret;

  double rs = sqrt(dfr);
  Point sgn = (c2.c - c1.c) / d;
  ret.push_back(c1.c + sgn*Point(rc, rs));
  if (dfr > 0.0) ret.push_back(c1.c + sgn*Point(rc, -rs));
  return ret;
}

int n;
double A, B, C;
Point rocks[50];
int mind[11451419];
bool considered[30][30][30][30];
bool result[30][30][30][30];

void NormalizeNum(int *nums) {
  if (nums[0] > nums[1]) swap(nums[0], nums[1]);
  if (nums[2] > nums[3]) swap(nums[2], nums[3]);
}

int CalcState(int *nums, bool *is_goal) {
  int state = 0;
  for (int i=0; i<4; i++) {
    state = state*31 + nums[i];
    if (nums[i] == n && is_goal) *is_goal = true;
  }
  return state;
}

void State2Num(int state, int *nums) {
  for (int i=0; i<4; i++) {
    nums[3-i] = state%31;
    state /= 31;
  }
}

bool IsPossible(int a, int b, int c, int d) {
  if (considered[a][b][c][d]) return result[a][b][c][d];
  considered[a][b][c][d] = true;

  Circle cs[] = {{rocks[a], A}, {rocks[b], A}, {rocks[c], C}, {rocks[d], C}};
  vector<Point> cc1 = CrossPointCC(cs[0], cs[1]);
  vector<Point> cc2 = CrossPointCC(cs[2], cs[3]);
  if (cc1.empty()) return false;
  if (cc2.empty()) return false;

  vector<Point> rough_cand1(cc1);
  vector<Point> rough_cand2(cc2);
  for (int i=0; i<2; i++) {
    for (int j=2; j<4; j++) {
      Line l(cs[i].c, cs[j].c);
      for (int k=0; k<2; k++) {
        vector<Point> cl = CrossPointCL(cs[k], l);
        rough_cand1.insert(rough_cand1.end(), cl.begin(), cl.end());
        rough_cand2.insert(rough_cand2.end(), cl.begin(), cl.end());
      }

      for (int k=2; k<4; k++) {
        vector<Point> cl = CrossPointCL(cs[k], l);
        rough_cand2.insert(rough_cand2.end(), cl.begin(), cl.end());
      }
    }
  }

  for (int i=0; i<2; i++) {
    for (Point p2 : cc2) {
      Line l(cs[i].c, p2);
      for (int j=0; j<2; j++) {
        vector<Point> cl1 = CrossPointCL(cs[j], l);
        rough_cand1.insert(rough_cand1.end(), cl1.begin(), cl1.end());
      }
    }
  }

  for (int i=2; i<4; i++) {
    for (Point p1 : cc1) {
      Line l(cs[i].c, p1);
      for (int k=2; k<4; k++) {
        vector<Point> cl2 = CrossPointCL(cs[k], l);
        rough_cand2.insert(rough_cand2.end(), cl2.begin(), cl2.end());
      }
    }
  }
  
  vector<Point> cand1;
  vector<Point> cand2;

  for (Point p1 : rough_cand1) {
    if (abs(p1-cs[0].c) >= cs[0].r + EPS) continue;
    if (abs(p1-cs[1].c) >= cs[1].r + EPS) continue;
    cand1.push_back(p1);
  }

  for (Point p2 : rough_cand2) {
    if (abs(p2-cs[2].c) >= cs[2].r + EPS) continue;
    if (abs(p2-cs[3].c) >= cs[3].r + EPS) continue;
    cand2.push_back(p2);
  }

  sort(cand1.begin(), cand1.end());
  cand1.erase(unique(cand1.begin(), cand1.end()), cand1.end());
  sort(cand2.begin(), cand2.end());
  cand2.erase(unique(cand2.begin(), cand2.end()), cand2.end());
  for (Point p1 : cand1) {
    for (Point p2 : cand2) {
      if (abs(p1-p2) < B+EPS) return result[a][b][c][d] = true;
    }
  }

  return result[a][b][c][d] = false;
}

int main() {
  scanf("%d", &n);
  scanf("%lf%lf%lf", &A, &B, &C);
  swap(A, B);
  for (int i=0; i<n; i++) {
    double x, y;
    scanf("%lf%lf", &x, &y);
    rocks[i] = Point(x, y);
  }

  int ans = INF;
  queue<int> q;
  fill(mind, mind+11451419, INF);
  for (int i=0; i<4; i++) {
    int nums[] = {1, 2, 3, 4};

    nums[i] = 0;
    NormalizeNum(nums);            
                         
    bool is_goal = false;
    int state = CalcState(nums, &is_goal);          
    mind[state] = 0;
    q.push(state);
    if (is_goal) {
      puts("0");
      return 0;
    }
  }

  while (!q.empty()) {
    int state = q.front(); q.pop();
    int nums[4];
    State2Num(state, nums);

    if (nums[0] == 0) {
      int b = nums[1]-1;
      int c = nums[2]-1;
      int d = nums[3]-1;

      for (int a=0; a<n; a++) {
        if (b == a || c == a || d == a) continue;

        if (IsPossible(a, b, c, d)) {
          //printf("%d %d %d %d\n", a, b, c, d);
          for (int j=1; j<4; j++) {
            int nums2[4];

            memcpy(nums2, nums, sizeof(nums2));
            nums2[0] = a+1;
            nums2[j] = 0;
            NormalizeNum(nums2);

            bool is_goal = false;
            int next_state = CalcState(nums2, &is_goal);
            if (is_goal) {
              printf("%d\n", mind[state]+1);
              return 0;
            }

            if (mind[next_state] > mind[state]+1) {
              mind[next_state] = mind[state]+1;
              q.push(next_state);
            }
          }
        }
      }
    } else {
      int a = nums[0]-1;
      int b = nums[1]-1;
      int d = nums[3]-1;

      for (int c=0; c<n; c++) {
        if (a == c || b == c || d == c) continue;

        if (IsPossible(a, b, c, d)) {
          //printf("%d %d %d %d\n", a, b, c, d);
          for (int j=0; j<4; j++) {
            if (j == 2) continue;

            int nums2[4];

            memcpy(nums2, nums, sizeof(nums2));
            nums2[2] = c+1;
            nums2[j] = 0;
            NormalizeNum(nums2);

            bool is_goal = false;
            int next_state = CalcState(nums2, &is_goal);
            if (is_goal) {
              printf("%d\n", mind[state]+1);
              return 0;
            }

            if (mind[next_state] > mind[state]+1) {
              mind[next_state] = mind[state]+1;
              q.push(next_state);
            }
          }
        }
      }
    }
  }

  puts("-1");
}

Measured memory_bytes: 49164