#include <bits/stdc++.h>
const int N_MAX = 4403;
int n, m, a[N_MAX], b[N_MAX];
struct Data {
  long long x, y;
  int id;
  Data() {}
  Data(long long x, long long y, int id) : x(x), y(y), id(id) {}
} arr[N_MAX];
inline bool cmpX(const Data &lhs, const Data &rhs) {
  return lhs.x != rhs.x ? lhs.x < rhs.x : lhs.id > rhs.id;
}
inline bool cmpY(const Data &lhs, const Data &rhs) {
  return lhs.y != rhs.y ? lhs.y < rhs.y : lhs.id > rhs.id;
}
const int M_MAX = 17603, S = M_MAX - 2, T = M_MAX - 1, E_MAX = 100003;
int h[M_MAX], cntE = 1;
struct Edge {
  int tar, flow, cost, nxt;
  Edge() {}
  Edge(int tar, int flow, int cost, int nxt)
      : tar(tar), flow(flow), cost(cost), nxt(nxt) {}
} ed[E_MAX];
inline void addEdge(int x, int y, int z, int w) {
  ed[++cntE] = Edge(y, z, w, h[x]), h[x] = cntE;
  ed[++cntE] = Edge(x, 0, -w, h[y]), h[y] = cntE;
}
const int DIS_MAX = 0x3f3f3f3f;
int dis[M_MAX], preEd[M_MAX], preVer[M_MAX];
inline bool SPFA() {
  memset(dis + 1, 0x3f, sizeof(dis[0]) * m * 4), dis[S] = 0, dis[T] = DIS_MAX;
  std::queue<int> que;
  que.push(S);
  while (!que.empty()) {
    int x = que.front();
    que.pop();
    for (int i = h[x], y; i; i = ed[i].nxt)
      if (ed[i].flow && dis[y = ed[i].tar] > dis[x] + ed[i].cost) {
        dis[y] = dis[x] + ed[i].cost, que.push(y);
        preEd[y] = i, preVer[y] = x;
      }
  }
  return dis[T] < DIS_MAX;
}
const int FLOW_MAX = 0x3f3f3f3f;
inline int EK() {
  int maxFlow = 0, minCost = 0;
  while (SPFA()) {
    int temp = FLOW_MAX;
    for (int x = T; x != S; x = preVer[x])
      temp = std::min(temp, ed[preEd[x]].flow);
    maxFlow += temp;
    int sum = 0;
    for (int x = T; x != S; x = preVer[x]) {
      ed[preEd[x]].flow -= temp, ed[preEd[x] ^ 1].flow += temp;
      sum += ed[preEd[x]].cost;
    }
    assert(sum == dis[T]);
    minCost += sum * temp;
  }
  assert(maxFlow == n);
  return minCost;
}
int main() {
  scanf("%d", &n), m = n * 2;
  for (int i = 1; i <= m; ++i) scanf("%d%d", &a[i], &b[i]);
  const int limit = 1e9 + 7;
  int l = 0, r = limit;
  while (l < r) {
    const int mid = (l + r) >> 1;
    for (int i = 1; i <= m; ++i)
      arr[i] = Data(b[i], 1ll * mid * a[i] + b[i], i);
    std::sort(arr + 1, arr + m + 1, cmpX);
    std::multiset<long long> st;
    long long mx = 0;
    for (int i = 1; i <= m; ++i) {
      mx = std::max(mx, arr[i].y);
      if (arr[i].id <= n) st.insert(mx);
    }
    std::sort(arr + 1, arr + m + 1, cmpY);
    bool valid = 1;
    for (int i = 1; i <= m; ++i)
      if (arr[i].id > n) {
        std::multiset<long long>::iterator it = st.lower_bound(arr[i].y);
        if (it == st.end()) {
          valid = 0;
          break;
        }
        st.erase(it);
      }
    valid ? r = mid : l = mid + 1;
  }
  if (r == limit) {
    printf("-1\n");
    return 0;
  }
  for (int i = 1; i <= n; ++i) addEdge(S, i, 1, 0);
  for (int i = n + 1; i <= m; ++i) addEdge(i + m, T, 1, 0);
  for (int i = 1; i <= m; ++i) {
    arr[i] = Data(b[i], 1ll * l * a[i] + b[i], i);
    addEdge(i, i + m, FLOW_MAX, 0);
    addEdge(i + m * 2, i, FLOW_MAX, 1);
    addEdge(i + m * 3, i + m, FLOW_MAX, 1);
  }
  std::sort(arr + 1, arr + m + 1, cmpX);
  for (int i = 1; i < m; ++i) {
    addEdge(arr[i + 1].id, arr[i].id + m * 2, FLOW_MAX, 0);
    addEdge(arr[i + 1].id + m * 2, arr[i].id + m * 2, FLOW_MAX, 0);
  }
  std::sort(arr + 1, arr + m + 1, cmpY);
  for (int i = 1; i < m; ++i) {
    addEdge(arr[i + 1].id + m, arr[i].id + m * 3, FLOW_MAX, 0);
    addEdge(arr[i + 1].id + m * 3, arr[i].id + m * 3, FLOW_MAX, 0);
  }
  printf("%d %d\n", l, EK());
  return 0;
}
