int main(){
  ll answer = 0;
  int n;
  scanf("%d", &n);
  ll tutorsx  [n]; memset(tutorsx  , 0, sizeof(tutorsx  ));
  ll tutorsy  [n]; memset(tutorsy  , 0, sizeof(tutorsy  ));
  ll studentsx[n]; memset(studentsx, 0, sizeof(studentsx));
  ll studentsy[n]; memset(studentsy, 0, sizeof(studentsy));
  for(int i=0; i<n; i++)
    scanf("%lld %lld", &studentsx[i], &studentsy[i]);
  for(int i=0; i<n; i++)
    scanf("%lld %lld", &tutorsx[i], &tutorsy[i]);
  ll distances[n][n];
  for(int i=0; i<n; i++)
    for(int j=0; j<n; j++)
      distances[i][j] = abs(tutorsx[i] - studentsx[j]) + 
                        abs(tutorsy[i] - studentsy[j]);
  ll low = 0, high = 10000000000, mid;
  while(high - low > 2){
    init(n, n);
    mid = (low + high) / 2;
    for(int i = 0; i < n; i++)
      for(int j = 0; j < n; j++)
        if(distances[i][j] <= mid)
          addEdge(i, j);
    if(maxMatching() == n)
      high = mid + 1;
    else if(maxMatching() < n)
      low = mid + 1;
  }
  init(n, n);
  for(int i = 0; i < n; i++)
      for(int j = 0; j < n; j++)
        if(distances[i][j] <= low)
          addEdge(i, j);
  if(maxMatching() == n)
    answer = low;
  else
    answer = low + 1;
  printf("%lld\n", answer);
  return 0;
}
// assign rooms to events in timeslot t
void Solution::assignRooms(int t)
{
    val.clear();
    dad.clear();
    vector<int> assigned; // vector keeping track for each event if it is assigned or not
    int lessBusy= 0; // room occupied by the fewest events
    int busy[data->n_of_rooms]; // number of events in a room
    int N = (int)timeslot_events[t].size();
    int V = N+2+data->n_of_rooms;
    // initialize the bipartite graph
    size = IntMatrixAlloc(V+1,V+1);
    flow = IntMatrixAlloc(V+1,V+1);
    for (int i = 0; i <= V; i++) {
        for (int j = 0; j <= V; j++) {
            size[i][j] = 0;
            flow[i][j] = 0;
        }
    }
    for(int i =0; i < N; i++){
        size[1][i+2] = 1;
        size[i+2][1] = -1;
        for(int j = 0; j < data->n_of_rooms; j++)
            if(data->possibleRooms[timeslot_events[t][i]][j] == 1){
                size[i+2][N+j+2] = 1;
                size[N+j+2][i+2] = -1;
                size[N+j+2][V] = 1;
                size[V][N+j+2] = -1;
            }
    }
    maxMatching(V); // apply the matching algorithm
    for(int i =0; i < N; i++){ // check if there are unplaced events
        assigned.push_back(0);
        for(int j = 0; j < data->n_of_rooms; j++){
            if(flow[i+2][N+j+2] == 1){
                sln[timeslot_events[t][i]].second = j;
                // cout << "room " << j << endl;
                assigned[i] = 1;
                //busy[j] =+ 1;
                busy[j] += 1;
            }
        }
    }
    for(int i = 0; i < N; i++){ // place the unplaced events in the less busy possible rooms
        if(assigned[i] == 0){
            for(int j = 0; j < data->n_of_rooms; j++){
                if(data->possibleRooms[timeslot_events[t][i]][j] == 1){
                    lessBusy = j;
                    break;
                }
            }
            for(int j = 0; j < data->n_of_rooms; j++){
                if(data->possibleRooms[timeslot_events[t][i]][j] == 1){
                    if(busy[j] < busy[lessBusy])
                        lessBusy = j;
                }
            }
            sln[timeslot_events[t][i]].second = lessBusy;
        }
    }
    free(size); // don't forget to free the memory
    free(flow);
}