import std.stdio;
import std.range;
import std.container;
import std.algorithm;
import std.array;
import std.string;
import std.functional;
import std.conv;
import std.typecons;

struct P {
    int y, x, level;
    int opCmp(P o) {
        return level - o.level;
    }
}

int R;

int[] init() {
    int W, H, X, Y; readf("%d %d %d %d\n", &W, &H, &X, &Y);
    X--; Y--;
    int[][] F = new int[][H];
    foreach (i; 0 .. H) {
        F[i] = readln.chomp.split(" ").map!(to!int).array;
    }
    bool[][] used = new bool[][](H, W);
    bool[][] usedPQ = new bool[][](H, W);
    int[] L;
    DList!P Q;
    Q.insert(P(Y, X, F[Y][X])); used[Y][X] = true;
    BinaryHeap!(Array!P, "a >= b") PQ;
    static const dy = [0, 1, 0, -1],
                 dx = [1, 0, -1, 0];
    while (true) {
        if (Q.empty) {
            if (PQ.empty) break;
            P next = PQ.front; PQ.removeFront;
            if (used[next.y][next.x]) continue;
            Q.insert(next);
            used[next.y][next.x] = true;
        } else {
            P cur = Q.front; Q.removeFront;
            L ~= cur.level;
            if (L.length >= R) break;
            F[cur.y][cur.x] = cur.level;
            foreach (i; 0 .. 4) {
                int ny = cur.y + dy[i],
                    nx = cur.x + dx[i];
                if (ny < 0 || ny >= H) continue;
                if (nx < 0 || nx >= W) continue;
                if (used[ny][nx]) continue;
                if (F[ny][nx] <= cur.level) {
                    Q.insert(P(ny, nx, cur.level));
                    used[ny][nx] = true;
                } else {
                    if (usedPQ[ny][nx]) continue;
                    usedPQ[ny][nx] = true;
                    PQ.insert(P(ny, nx, F[ny][nx]));
                }
            }
        }
    }
    //foreach (ref _; F) _.writeln;
    return L;
}

int countUnder(int[] L, int k) {
    int lb = 0, ub = cast(int)L.length;
    if (L[lb] > k) return 0;
    while (lb + 1 < ub) {
        int mid = (lb + ub) / 2;
        if (L[mid] <= k) {
            lb = mid;
        } else {
            ub = mid;
        }
    }
    //"countUnder".writeln([k, ub]);
    return ub;
}

void main() {
    while (readf("%d\n", &R), R) {
        int[][] L = new int[][2];
        foreach (i; 0 .. 2) {
            L[i] = init;
        }
        auto X = [0] ~ L[0].uniq.array;
        //X.map!(a => [a, countUnder(L[0], a)]).writeln;
        auto Y = [0] ~ L[1].uniq.array;
        //Y.map!(a => [a, countUnder(L[1], a)]).writeln;
        int ans = int.max;
        foreach (x; X) {
            int c = L[0].countUnder(x);
            if (c >= R) {
                ans = min(ans, x);
                break;
            }
            int r = R - c;
            if (r > L[1].length) continue;
            int lb = 0, ub = cast(int)Y.length - 1;
            if (L[1].countUnder(Y[lb]) >= r) {
                ans = min(ans, x + Y[lb]);
                continue;
            }
            assert(L[1].countUnder(Y[ub]) >= r);
            while (lb + 1 < ub) {
                int mid = (lb + ub) / 2;
                if (L[1].countUnder(Y[mid]) >= r) {
                    ub = mid;
                } else {
                    lb = mid;
                }
            }
            ans = min(ans, x + Y[ub]);
        }
        ans.writeln;
    }
}

Measured memory_bytes: 8408