#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#include <cstdio>

using namespace std;

const int N = 500;
const int INF = 1000000000;

class S{
public:
  int x, y, cost;
  S(){}
  S(int x, int y, int cost) : x(x), y(y), cost(cost) {}
  bool operator < (const S& s) const {
    return cost > s.cost;
  }
};

int R, w[2], h[2], sx[2], sy[2], input[2][N][N], vis[N][N];
int dx[] = {0, 1, 0, -1};
int dy[] = {-1, 0, 1, 0};
vector<int> vec[2];
set<int> used;
vector<int> data;
int cnt;

/*void dfs(int x, int y, int cost, int d){
  vis[y][x] = true;
  cnt++;
  for(int i=0;i<4;i++){
    int ny = y + dy[i];
    int nx = x + dx[i];
    if(ny < 0 || ny >= h[d]) continue;
    if(nx < 0 || nx >= w[d]) continue;
    if(input[d][ny][nx] > cost) continue;
    if(!vis[ny][nx]) dfs(nx, ny, cost, d);
  }
  }*/

void bfs(int d){
  int x = sx[d];
  int y = sy[d];
  int cost = 1;
  priority_queue<S> q;
  S u;
  q.push(S(x, y, cost));
  vis[y][x] = cost;
  while(!q.empty()){
    u = q.top(); q.pop();
    if(vis[u.y][u.x] < u.cost) continue;
    for(int i=0;i<4;i++){
      int ny = u.y + dy[i];
      int nx = u.x + dx[i];
      if(ny < 0 || ny >= h[d]) continue;
      if(nx < 0 || nx >= w[d]) continue;
      int tmp = max(u.cost, input[d][ny][nx]);
      if(vis[ny][nx] > tmp){
        vis[ny][nx] = tmp;
        q.push(S(nx, ny, tmp));
      }
    }
  }
}

void init(){
  //used.clear();
  data.clear();
  for(int k=0;k<2;k++){
    for(int i=0;i<h[k];i++){
      for(int j=0;j<w[k];j++){
        /*if(!used.count(input[k][i][j])){
          used.insert(input[k][i][j]);
          data.push_back(input[k][i][j]);
          }*/
        data.push_back(input[k][i][j]);
      }
    }
  }
  sort(data.begin(), data.end());
  for(int k=0;k<2;k++){
    /*int vis2[N][N];
    fill(vis2[0], vis2[N], INF);
    set<int>::iterator ite = data.begin();
    for(;ite!=data.end();ite++){
      fill(vis[0], vis[N], false);
      dfs(sx[k], sy[k], *ite, k);      
      for(int i=0;i<h[k];i++){
        for(int j=0;j<w[k];j++){
          if(vis[i][j]) vis2[i][j] = min(vis2[i][j], *ite);
        }
      }
      }*/
    fill(vis[0], vis[N], INF);
    for(int i=0;i<h[k];i++){
      for(int j=0;j<w[k];j++){
        vis[i][j] = INF;
      }
    }
    bfs(k);

    vec[k].clear();
    for(int i=0;i<h[k];i++){
      for(int j=0;j<w[k];j++){
        //vec[k].push_back(vis2[i][j]);
        vec[k].push_back(vis[i][j]);
      }
    }
    sort(vec[k].begin(), vec[k].end());
  }
}

bool check(int a, int b){
  int t1 = distance(vec[0].begin(), upper_bound(vec[0].begin(), vec[0].end(), a));
  int t2 = distance(vec[1].begin(), upper_bound(vec[1].begin(), vec[1].end(), b));
  return t1 + t2 >= R;
  /*int sum = 0;
  for(int i=0;i<2;i++){
    fill(vis[0], vis[N], false);
    cnt = 0;
    int cost = a;
    if(i == 1) cost = b;
    if(cost > 0) dfs(sx[i], sy[i], cost, i);
    sum += cnt;
  }
  return sum >= R;*/
}

int solve(){
  //set<int>::iterator ite = data.end();
  //int l = 0, r = *(--ite) + 1;
  int l = 0, r = data[data.size()-1] + 1;
  while(l<r){
    int m = (l + r) / 2;
    bool f = false;
    //for(ite=data.begin();ite!=data.end();ite++){
    for(int i=0;i<data.size();i++){
      //if(*ite > m) break;
      if(data[i] > m) break;
      //if(check(*ite, m-(*ite))) f = true;
      if(check(data[i], m-data[i])) f = true;
    }
    if(f) r = m;
    else l = m + 1;
  }
  return l;
}

main(){
  //while(cin >> R && R){
  while(scanf("%d", &R) && R){
    for(int k=0;k<2;k++){
      scanf("%d %d %d %d", w+k, h+k, sx+k, sy+k);
      //cin >> w[k] >> h[k] >> sx[k] >> sy[k];
      sx[k]--; sy[k]--;
      for(int i=0;i<h[k];i++){
        for(int j=0;j<w[k];j++){
          //cin >> input[k][i][j];
          scanf("%d", &input[k][i][j]);
        }
      }
    }
    init();
    //cout << solve() << endl;
    printf("%d\n", solve());
  }
}

Measured memory_bytes: 9240