#include<iostream>
#include<vector>
#include<queue>
#include<map>

#define MAX 512
using namespace std;

typedef pair<int,int> pi;
typedef pair< int, pi > lvq;

struct lvloc{
  int lv;
  vector< pi > locs;
  bool operator<(const lvloc &t)const{
    return lv > t.lv;
  }
};

const int di[] = {-1,0,1,0};
const int dj[] = {0,1,0,-1};
const int infty = 1<<29;

struct Office{
  int W,H;
  int X,Y;
  int M[MAX][MAX];
  vector< pi > AuthenticationLevel;

  Office():W(0),H(0),X(0),Y(0){}
  Office(int W, int H, int X, int Y):W(W),H(H),X(X-1),Y(Y-1){}

  bool isinside(pi p)const{ return 0<=p.first&&p.first<H&&0<=p.second&&p.second<W; }

  void CheckSecurity(){
    int total = 0;
    priority_queue< lvloc > nextQ;
    bool vis[MAX][MAX] = {{false,},};
    lvloc init;
    init.lv = 1;
    init.locs.push_back( pi(Y,X) );
    nextQ.push( init );

    
    while(!nextQ.empty()){
      lvloc nlv = nextQ.top();
      int newcnt = 0;
      nextQ.pop();

      queue<lvq> Q;
      for(int i = 0; i < nlv.locs.size(); ++i){
	++newcnt;
	++total;
	Q.push( lvq( nlv.lv, nlv.locs[i] ) );
	vis[ nlv.locs[i].first ][ nlv.locs[i].second ] = true;
      }
      int level;
      map< int, vector<pi> > T;

      while(!Q.empty()){
	lvq now = Q.front();
	Q.pop();
	level = now.first;
	pi pos = now.second;

	for(int k = 0; k < sizeof(di)/sizeof(*di); ++k){
	  pi nxpos = pi( pos.first + di[k], pos.second + dj[k] );
	  if( isinside( nxpos ) ){
	    if( M[ nxpos.first ][ nxpos.second ] <= level ){
	      if( !vis[ nxpos.first ][ nxpos.second ] ){
		vis[ nxpos.first ][ nxpos.second ] = true;
		++newcnt;++total;
		Q.push( lvq( level, nxpos ) );
	      }
	    }else{
	      if( !vis[nxpos.first][nxpos.second ] ){
		vis[nxpos.first][nxpos.second]=true;
		T[ M[ nxpos.first ][ nxpos.second ] ].push_back( nxpos );
	      }
	    }
	  }
	}
      }

      AuthenticationLevel.push_back( pi( level, total ) );
      

      for(map<int,vector<pi> >::iterator itm = T.begin();
	  itm != T.end(); ++itm ){
	lvloc nextlvloc;
	nextlvloc.lv = itm->first;
	nextlvloc.locs = itm->second;
	nextQ.push( nextlvloc );
      }

    }    
  }
};
int binsearch( const vector< pi > & vpi, int v ){
  int R=vpi.size();
  int L=0;
  int M;
  int preM=-1;
  while(true){
    M=(R+L)/2;
    if(preM==M)break;
    if( vpi[M].second > v ){
      R=M;
    }else if( vpi[M].second == v ){
      return vpi[M].first;
    }else{
      L=M;
    }
    preM=M;
  }
  if( vpi[M].second < v ){
    if( M+1 < vpi.size() ) return vpi[M+1].first;
    else return infty;
  }else{
    return vpi[M].first;
  }
}

int main()
{
  while(true){
    int ans = infty;
    int R;
    scanf("%d", &R);
    if( R == 0 ) break;
    static Office office[2];
    for(int x = 0; x < 2; ++x){
      int W,H,X,Y;
      scanf("%d%d%d%d", &W, &H, &X, &Y);
      office[x] = Office(W,H,X,Y);
      for(int i = 0; i < H; ++i){
	for(int j = 0; j < W; ++j){
	  scanf("%d" , &office[x].M[i][j] );
	}
      }
      office[x].CheckSecurity();
      /*      
      cout << "Authentication levels : Office " << 1+x << endl;
      for(int i = 0; i < office[x].AuthenticationLevel.size(); ++i){
	cout << "Level : " << office[x].AuthenticationLevel[i].first << " -> " << 
	  office[x].AuthenticationLevel[i].second << endl;
      }
      */
    }
    ans = min( binsearch(office[0].AuthenticationLevel, R ), binsearch(office[1].AuthenticationLevel, R ) );
    for(int i = 0; i < office[0].AuthenticationLevel.size(); ++i){
      ans = min (ans, office[0].AuthenticationLevel[i].first + binsearch( office[1].AuthenticationLevel, R - office[0].AuthenticationLevel[i].second ) );
    }
    cout << ans << endl;
  }
  return 0;
}

Measured memory_bytes: 7060