#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int INF = 1e9;
const int MAX_N = 4405;
int N, a[MAX_N], b[MAX_N];
LL eval(int o, int x) { return 1ll * a[o] * x + b[o]; }
int Id[MAX_N];
bool check(int mid) {
  vector<LL> v1, v2;
  LL mx = 0;
  for (int i = 1; i <= N << 1; i++) {
    mx = max(mx, eval(Id[i], mid));
    if (Id[i] <= N) v1.push_back(mx);
  }
  for (int i = N + 1; i <= N << 1; i++) v2.push_back(eval(i, mid));
  sort(v2.begin(), v2.end());
  for (int i = 0; i < (int)v1.size(); i++)
    if (v1[i] < v2[i]) return 0;
  return 1;
}
struct Graph {
  int to, cap, cost, next;
} e[MAX_N * 100];
int fir[MAX_N << 2], e_cnt;
void clearGraph() {
  memset(fir, -1, sizeof(fir));
  e_cnt = 0;
}
void Add_Edge(int u, int v, int c, int w) {
  e[e_cnt] = (Graph){v, c, w, fir[u]}, fir[u] = e_cnt++;
  e[e_cnt] = (Graph){u, 0, -w, fir[v]}, fir[v] = e_cnt++;
}
int S, T, dis[MAX_N << 2], inq[MAX_N << 2];
bool spfa() {
  for (int i = 0; i <= T; i++) dis[i] = INF, inq[i] = 0;
  queue<int> que;
  dis[S] = 0, que.push(S), inq[S] = 1;
  while (!que.empty()) {
    int x = que.front();
    que.pop();
    for (int i = fir[x]; ~i; i = e[i].next) {
      int v = e[i].to, w = e[i].cost;
      if (e[i].cap && dis[x] + w < dis[v]) {
        dis[v] = dis[x] + w;
        if (!inq[v]) inq[v] = 1, que.push(v);
      }
    }
    inq[x] = 0;
  }
  return dis[T] != INF;
}
int dfs(int x, int f) {
  if (x == T || !f) return f;
  inq[x] = 1;
  int res = 0;
  for (int i = fir[x]; ~i; i = e[i].next) {
    int v = e[i].to, w = e[i].cost;
    if (e[i].cap && dis[x] + w == dis[v] && !inq[v]) {
      int d = dfs(v, min(f, e[i].cap));
      if (d) {
        e[i].cap -= d, e[i ^ 1].cap += d;
        f -= d, res += d;
        if (!f) break;
      }
    }
  }
  if (!res) dis[x] = INF;
  return res;
}
int mcmf() {
  int res = 0;
  while (spfa()) res += dfs(S, INF) * dis[T];
  return res;
}
int main() {
  scanf("%d", &N);
  for (int i = 1; i <= N << 1; i++) scanf("%d %d", a + i, b + i);
  for (int i = 1; i <= N << 1; i++) Id[i] = i;
  sort(&Id[1], &Id[N << 1 | 1], [](const int &i, const int &j) {
    return b[i] < b[j] || (b[i] == b[j] && i > j);
  });
  int l = 0, r = 1e9, res = -1;
  while (l <= r) {
    int mid = (l + r) >> 1;
    if (check(mid))
      res = mid, r = mid - 1;
    else
      l = mid + 1;
  }
  if (res == -1) return puts("-1") & 0;
  printf("%d ", res);
  clearGraph();
  S = 0, T = N * 6 + 1;
  for (int i = 1; i <= N; i++) Add_Edge(S, i, 1, 0);
  for (int i = 2; i <= N << 1; i++)
    Add_Edge(Id[i] + 4 * N, Id[i - 1] + 4 * N, INF, 0);
  for (int i = 2; i <= N << 1; i++) Add_Edge(Id[i], Id[i - 1], INF, 0);
  for (int i = 1; i <= N << 1; i++) {
    Add_Edge(i, i + 4 * N, INF, 1);
    Add_Edge(i + 4 * N, i + 2 * N, 1, 0);
    Add_Edge(i + 4 * N, i + 2 * N, INF, 1);
  }
  sort(&Id[1], &Id[N << 1 | 1], [&](const int &i, const int &j) {
    return eval(i, res) < eval(j, res) ||
           (eval(i, res) == eval(j, res) && i > j);
  });
  for (int i = 2; i <= N << 1; i++)
    Add_Edge(Id[i] + 2 * N, Id[i - 1] + 2 * N, INF, 0);
  for (int i = N + 1; i <= N << 1; i++) Add_Edge(i + N * 2, T, 1, 0);
  printf("%d\n", mcmf());
  return 0;
}
