//認証レベルの小さい順に鍵を設定すると、入れる部屋が単調にふえるので、その部屋に入るための最少認証レベルが簡単に求まる。
//と思ったら、そうでもなかった…とりあえず、ダイクストラの負の辺OK盤を使う。
#include<iostream>
#include<vector>
#include<queue>
#include<map>
//#define DEBUG DEBUG
#define F first
#define S second
using namespace std;
#define MAX(x,y) (x>y?x:y)	// ()がいります
typedef pair<int,int> P;
typedef pair<int,P> PP;
int R;
int W1,H1,X1,Y1,W2,H2,X2,Y2;
int JOI1[501][501],JOI2[501][501];	//JOI[y][x]として入れます。
int ADD1[501][501],ADD2[501][501];	//入るための認証レベルの最小値(1以上)

void Make_list1(){
	priority_queue<PP,vector<PP>,greater<PP> > que;
	PP node;
	que.push(PP(1,P(Y1,X1)));
	while(!que.empty()){
		node = que.top();
		que.pop();
		//周り4辺を更新
		if(ADD1[node.S.F+1][node.S.S] > MAX(node.F,JOI1[node.S.F+1][node.S.S])){
			ADD1[node.S.F+1][node.S.S] = MAX(node.F,JOI1[node.S.F+1][node.S.S]);
			que.push(PP(ADD1[node.S.F+1][node.S.S],P(node.S.F+1,node.S.S)));	
		}
		if(ADD1[node.S.F][node.S.S+1] > MAX(node.F,JOI1[node.S.F][node.S.S+1])){
			ADD1[node.S.F][node.S.S+1] = MAX(node.F,JOI1[node.S.F][node.S.S+1]);
			que.push(PP(ADD1[node.S.F][node.S.S+1],P(node.S.F,node.S.S+1)));	
		}
		if(node.S.F > 0 && ADD1[node.S.F-1][node.S.S] > MAX(node.F,JOI1[node.S.F-1][node.S.S])){
			ADD1[node.S.F-1][node.S.S] = MAX(node.F,JOI1[node.S.F-1][node.S.S]);
			que.push(PP(ADD1[node.S.F-1][node.S.S],P(node.S.F-1,node.S.S)));	
		}
		if(node.S.S > 0 && ADD1[node.S.F][node.S.S-1] > MAX(node.F,JOI1[node.S.F][node.S.S-1])){
			ADD1[node.S.F][node.S.S-1] = MAX(node.F,JOI1[node.S.F][node.S.S-1]);
			que.push(PP(ADD1[node.S.F][node.S.S-1],P(node.S.F,node.S.S-1)));	
		}
	}
}
void Make_list2(){
	priority_queue<PP,vector<PP>,greater<PP> > que;
	PP node;
	que.push(PP(1,P(Y2,X2)));
	while(!que.empty()){
		node = que.top();
		que.pop();
		//周り4辺を更新
		if(ADD2[node.S.F+1][node.S.S] > MAX(node.F,JOI2[node.S.F+1][node.S.S])){
			ADD2[node.S.F+1][node.S.S] = MAX(node.F,JOI2[node.S.F+1][node.S.S]);
			que.push(PP(ADD2[node.S.F+1][node.S.S],P(node.S.F+1,node.S.S)));	
		}
		if(ADD2[node.S.F][node.S.S+1] > MAX(node.F,JOI2[node.S.F][node.S.S+1])){
			ADD2[node.S.F][node.S.S+1] = MAX(node.F,JOI2[node.S.F][node.S.S+1]);
			que.push(PP(ADD2[node.S.F][node.S.S+1],P(node.S.F,node.S.S+1)));	
		}
		if(node.S.F > 0 && ADD2[node.S.F-1][node.S.S] > MAX(node.F,JOI2[node.S.F-1][node.S.S])){
			ADD2[node.S.F-1][node.S.S] = MAX(node.F,JOI2[node.S.F-1][node.S.S]);
			que.push(PP(ADD2[node.S.F-1][node.S.S],P(node.S.F-1,node.S.S)));	
		}
		if(node.S.S > 0 && ADD2[node.S.F][node.S.S-1] > MAX(node.F,JOI2[node.S.F][node.S.S-1])){
			ADD2[node.S.F][node.S.S-1] = MAX(node.F,JOI2[node.S.F][node.S.S-1]);
			que.push(PP(ADD2[node.S.F][node.S.S-1],P(node.S.F,node.S.S-1)));	
		}
	}
}
int main(){
	int i,j;
	int minest[200],mcor = 0;
	for(i = 0;i < 200;i++){minest[i] = 1000000000;}
	while(1){
		cin >> R;
		if(R == 0)
			break;
		cin >> W1 >> H1 >> X1 >> Y1;
		X1--;Y1--;
		for(i = 0;i < H1;i++){
			for(j = 0;j < W1;j++){
				cin >> JOI1[i][j];
				ADD1[i][j] = 1000000001;
			}
		}
		ADD1[Y1][X1] = 1;
		cin >> W2 >> H2 >> X2 >> Y2;
		X2--;Y2--;
		for(i = 0;i < H2;i++){
			for(j = 0;j < W2;j++){
				cin >> JOI2[i][j];
				ADD2[i][j] = 1000000001;
			}
		}
		ADD2[Y2][X2] = 1;
		//幅優先探索で部屋に入るための認証レベルの最小値,R部屋入るための認証レベルの最小値を記録する。
		//認証レベルの設定はWH回したほうがよい。まちがっても、部屋数に対する認証レベルを探すO(R^2logWH)解法は行わない！
		//queueを使うとO(WH)で行ける。WH*最大4方向*最大4回更新
		Make_list1();
		Make_list2();
		//認証レベルに対して入れる部屋数を考えてみよう(ヒント→認証レベルがiのとき認証レベルがi-1のとき行けた部屋はすべていける)
		static map<int,int> nin1,nin2;	//認証レベル,部屋数
		nin1.insert(make_pair(0,0));
		for(i = 0;i < H1;i++){
			for(j = 0;j < W1;j++){
				if(nin1.find(ADD1[i][j]) == nin1.end()){
					nin1.insert(make_pair(ADD1[i][j],0));
				}
				nin1[ADD1[i][j]]++;		//2番目のキーをプラスしましょう。
			}
		}
		nin2.insert(make_pair(0,0));
		for(i = 0;i < H2;i++){
			for(j = 0;j < W2;j++){
				if(nin2.find(ADD2[i][j]) == nin2.end()){
					nin2.insert(make_pair(ADD2[i][j],0));
				}
				nin2[ADD2[i][j]]++;		//2番目のキーをプラスしましょう。
			}
		}
		map<int,int>::iterator it,bit;
		it = nin1.begin();
		for(it++;it != nin1.end();it++){
			bit = it;
			bit--;
			(*it).S += (*bit).S;
		}
		it = nin2.begin();
		for(it++;it != nin2.end();it++){
			bit = it;
			bit--;
			(*it).S += (*bit).S;
		}
		//入れる部屋数にたいする認証レベルの最小値を考えてみよう
		static int R1[100001],R2[100001];
		for(i = 0;i < R+1;i++){R1[i] = 1000000000;R2[i] = 1000000000;}
		it = nin1.begin();
		R1[0] = 0;
		it++;
		for(;it != nin1.end();it++){
			if((*it).S > R)
				(*it).S = R;
			bit = it;
			bit--;
			for(i = (*it).S;i > (*bit).S;i--){
				if(R1[i] > (*it).F)
					R1[i] = (*it).F;
			}
		}
		it = nin2.begin();
		R2[0] = 0;
		it++;
		for(;it != nin2.end();it++){
			if((*it).S > R)
				(*it).S = R;
			bit = it;
			bit--;
			for(i = (*it).S;i > (*bit).S;i--){
				if(R2[i] > (*it).F)
					R2[i] = (*it).F;
			}
		}
		//デバッグ
#ifdef DEBUG
		for(i = 0;i < H1;i++){
			for(j = 0;j < W1;j++){
				cout << ADD1[i][j] << " ";
			}
			cout << endl;
		}
		for(i = 0;i < H2;i++){
			for(j = 0;j < W2;j++){
				cout << ADD2[i][j] << " ";
			}
			cout << endl;
		}
		cout << "(NL,OK)1部屋目" << endl;
		for(it = nin1.begin();it != nin1.end();it++){
			cout << (*it).F << " " << (*it).S << endl;
		}
		cout << "(NL,OK)2部屋目" << endl;
		for(it = nin2.begin();it != nin2.end();it++){
			cout << (*it).F << " " << (*it).S << endl;
		}
		//認証レベル
		cout << "NL1部屋目" << endl;
		for(i = 0;i < H1;i++){
			for(j = 0;j < W1;j++){
				cout << R1[i*W1+j] << " ";
			}
			cout << endl;
		}
		cout << R1[H1*W1] << endl;
		cout << "NL2部屋目" << endl;
		for(i = 0;i < H2;i++){
			for(j = 0;j < W2;j++){
				cout << R2[i*W2+j] << " ";
			}
			cout << endl;
		}
		cout << R2[H1*W1] << endl;
#endif
		//探索(O(R))
		for(i = 0;i < R+1;i++){
			if(minest[mcor] > R1[i]+R2[R-i])
				minest[mcor] = R1[i]+R2[R-i];
		}		
		//使った分を初期化
		for(i = 0;i < H1;i++){
			for(j = 0;j < W1;j++){
				JOI1[i][j] = 0;
				ADD1[i][j] = 0;
			}
		}
		for(i = 0;i < H2;i++){
			for(j = 0;j < W2;j++){
				JOI2[i][j] = 0;
				ADD2[i][j] = 0;
			}
		}
		nin1.clear();
		nin2.clear();
		for(i = 0;i < R+1;i++){R1[i] = 1000000000;R2[i] = 1000000000;}
		//カーソル移動
		mcor++;
	}
	for(i = 0;i < mcor;i++){
		cout << minest[i] << endl;
	}
	return 0;
}