#include <bits/stdc++.h>
using namespace std;
template <typename T>
void maxtt(T &t1, T t2) {
  t1 = max(t1, t2);
}
template <typename T>
void mintt(T &t1, T t2) {
  t1 = min(t1, t2);
}
bool debug = 0;
int n, m, k;
int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
string direc = "URDL";
const long long MOD2 = (long long)998244353 * (long long)998244353;
long long ln, lk, lm;
void etp(bool f = 0) {
  puts(f ? "YES" : "NO");
  exit(0);
}
void addmod(int &x, int y, int mod = 998244353) {
  assert(y >= 0);
  x += y;
  if (x >= mod) x -= mod;
  assert(x >= 0 && x < mod);
}
void et(int x = -1) {
  printf("%d\n", x);
  exit(0);
}
long long fastPow(long long x, long long y, int mod = 998244353) {
  long long ans = 1;
  while (y > 0) {
    if (y & 1) ans = (x * ans) % mod;
    x = x * x % mod;
    y >>= 1;
  }
  return ans;
}
long long gcd1(long long x, long long y) { return y ? gcd1(y, x % y) : x; }
class MinCostFlow {
 public:
  int S, T, ecnt;
  int head[2200 * 11];
  int flw[2200 * 40], cost[2200 * 40], dis[2200 * 11];
  int to[2200 * 40], next[2200 * 40];
  bool use[2200 * 11];
  MinCostFlow() {
    memset(head, 0, sizeof(head));
    ecnt = 2;
  }
  void add_edge(int u, int v, int _c, int ww) {
    flw[ecnt] = _c;
    cost[ecnt] = ww;
    to[ecnt] = v;
    next[ecnt] = head[u];
    head[u] = ecnt++;
    flw[ecnt] = 0;
    cost[ecnt] = -ww;
    to[ecnt] = u;
    next[ecnt] = head[v];
    head[v] = ecnt++;
  }
  void SPFA() {
    for (int i = 1; i <= T; ++i) dis[i] = (1 << 29);
    priority_queue<pair<int, int> > Q;
    dis[S] = 0;
    Q.push(make_pair(0, S));
    while (!Q.empty()) {
      int u = Q.top().second, d = -Q.top().first;
      Q.pop();
      if (dis[u] != d) continue;
      for (int p = head[u]; p; p = next[p]) {
        int &v = to[p];
        if (flw[p] && dis[v] > d + cost[p]) {
          dis[v] = d + cost[p];
          Q.push(make_pair(-dis[v], v));
        }
      }
    }
    for (int i = 1; i <= T; ++i) dis[i] = dis[T] - dis[i];
  }
  int add_flow(int u, int flow, int &minCost) {
    if (u == T) {
      minCost += dis[S] * flow;
      return flow;
    }
    use[u] = true;
    int now = flow;
    for (int p = head[u]; p; p = next[p]) {
      int &v = to[p];
      if (flw[p] && !use[v] && dis[u] == dis[v] + cost[p]) {
        int tmp = add_flow(v, min(now, flw[p]), minCost);
        flw[p] -= tmp;
        flw[p ^ 1] += tmp;
        now -= tmp;
        if (!now) break;
      }
    }
    return flow - now;
  }
  bool modify_label() {
    int d = (1 << 29);
    for (int u = 1; u <= T; ++u)
      if (use[u])
        for (int p = head[u]; p; p = next[p]) {
          int &v = to[p];
          if (flw[p] && !use[v]) d = min(d, dis[v] + cost[p] - dis[u]);
        }
    if (d == (1 << 29)) return false;
    for (int i = 1; i <= T; ++i)
      if (use[i]) dis[i] += d;
    return true;
  }
  pair<int, int> minCostFlow(int s, int t) {
    S = s;
    T = t;
    SPFA();
    int flw = 0;
    int minCost = 0;
    while (true) {
      while (true) {
        for (int i = 1; i <= T; ++i) use[i] = 0;
        int tt = add_flow(S, (1 << 29), minCost);
        flw += tt;
        if (!tt) break;
      }
      if (!modify_label()) break;
    }
    return {flw, minCost};
  }
};
struct stock {
  int a, b, id;
  void rd(int z) {
    id = z;
    scanf("%d%d", &a, &b);
  }
  bool operator<(const stock &o) const { return b < o.b; }
  long long cal(int t) { return (long long)a * t + b; }
} stk[4444];
bool ck(int mid) {
  vector<long long> vp, vpt;
  long long pb = -(1LL << 60);
  for (int i = 1, j; i <= n + n; i = j) {
    for (j = i; j <= n + n && stk[i].b == stk[j].b; j++)
      ;
    for (int k = i; k < j; k++) maxtt(pb, stk[k].cal(mid));
    for (int k = i; k < j; k++)
      if (stk[k].id <= n) {
        vp.push_back(pb);
      }
  }
  for (int(i) = 1; (i) <= (int)(n + n); (i)++)
    if (stk[i].id > n) {
      vpt.push_back(stk[i].cal(mid));
    }
  sort(vp.begin(), vp.end());
  sort(vpt.begin(), vpt.end());
  for (int(i) = 0; (i) < (int)(n); (i)++)
    if (vp[i] < vpt[i]) return 0;
  return 1;
}
void fmain(int tid) {
  scanf("%d", &n);
  for (int(i) = 1; (i) <= (int)(n); (i)++) stk[i].rd(i);
  for (int(i) = 1; (i) <= (int)(n); (i)++) stk[i + n].rd(i + n);
  sort(stk + 1, stk + 1 + n + n);
  int l = 0, r = (1000000000);
  while (l + 1 < r) {
    int mid = (l + r) / 2;
    if (ck(mid))
      r = mid;
    else
      l = mid + 1;
  }
  int ans = ck(l) ? l : r;
  if (r == (1000000000)) et();
  printf("%d ", ans);
  MinCostFlow mf = MinCostFlow();
  int S = 1, T = n * 10 + 2;
  int n4 = n * 4;
  for (int(i) = 1; (i) <= (int)(n + n); (i)++) {
    if (stk[i].id <= n) mf.add_edge(S, i + 1, 1, 0);
    mf.add_edge(i + 1, i + 1 + n4, 1, 1);
    if (i != 1) mf.add_edge(i + 1 + n4, i + n4, n, 0);
    if (i == 1 || stk[i].b != stk[i - 1].b) {
      int j = i;
      while (j <= n + n && stk[j].b == stk[i].b) j++;
      j--;
      if (i != j) {
        mf.add_edge(i + 1 + n4, j + 1 + n4, n, 0);
      }
    }
  }
  vector<pair<long long, long long> > vp;
  for (int(i) = 1; (i) <= (int)(n + n); (i)++)
    vp.push_back({stk[i].cal(ans), i});
  sort(vp.begin(), vp.end());
  for (int(i) = 0; (i) < (int)(n + n); (i)++) {
    int id = vp[i].second;
    if (stk[id].id > n) {
      mf.add_edge(n + n + 2 + i, n + n + 2 + i + n * 6, 1, 0);
      mf.add_edge(n + n + 2 + i + n4, n + n + 2 + i + n * 6, 1, 0);
      mf.add_edge(n + n + 2 + i + n * 6, T, 1, 0);
    }
    mf.add_edge(n + n + 2 + i, n + n + 2 + i + n4, n, 1);
    if (i) mf.add_edge(n + n + 2 + i + n4, n + n + 1 + i + n4, n, 0);
    mf.add_edge(id + 1, n + n + 2 + i, n, 0);
    mf.add_edge(id + 1 + n4, n + n + 2 + i, n, 0);
    if (i == 0 || vp[i].first != vp[i - 1].first) {
      int j = i;
      while (j < n + n && vp[j].first == vp[i].first) j++;
      j--;
      if (i != j) {
        mf.add_edge(n + n + 2 + i + n4, n + n + 2 + j + n4, n, 0);
      }
    }
  }
  auto ynk = mf.minCostFlow(S, T);
  assert(ynk.first == n);
  printf("%d\n", ynk.second);
}
int main() {
  int t = 1;
  for (int(i) = 1; (i) <= (int)(t); (i)++) {
    fmain(i);
  }
  return 0;
}
