Problem:
認証レベル
問題
あなたは Just Odd Inventions 社を知っているだろうか? この会社の業務は「ただ奇妙な発明 (just odd inventions)」をすることである.ここでは略して JOI 社と呼ぶ.
JOI 社には 2 つの事務所があり,それぞれ同じ大きさの正方形の部屋がマス目状に並んでできている.辺で接しているすべての部屋の間に,身分証による認証機能の付いた扉がある.JOI 社では様々なレベルの機密情報を扱っているため,部屋ごとに機密レベルという正の整数が設定されており,身分証の事務所ごとに定められた非負整数の認証レベルが,機密レベル以上でないとその部屋に入室することができない.各事務所の出入り口は唯一あるエレベーターホールのみで,エレベーターホールの部屋の機密レベルは最低の 1 である.その事務所についての認証レベルが 0 のときはエレベーターホールに入ることさえできない.
JOI 社では,社長の突発的な提案で,一般の人に社内を見学してもらうツアーを実施することになった.あなたは見学者に渡す身分証の認証レベルの組み合わせを決める必要がある.見学者は開けられる扉を見つけると必ず開けて中に入る (同じ部屋を何度も訪れることも可能である).そのため,必要以上に見学者の身分証の認証レベルを高くしたくはない.しかし,ツアーに魅力を持たせるため,ツアーではエレベーターホールの部屋を含め 2 つの事務所であわせて R 個以上の部屋を訪れることができるようにする必要がある.身分証の認証レベルを低くしすぎると,この条件を満たすことができないかもしれない.
JOI 社には事務所が 2 個あり,第
k
事務所 (
k
= 1, 2) の部屋は東西方向に
W
k
個,南北方向に
H
k
個並んでおり,全部で
W
k
×
H
k
個ある. 西から
i
番目,北から
j
番目の部屋を (
i
,
j
)
k
で表すことにする.
W
k
と
H
k
と
R
の値,エレベーターホールの位置 (
X
k
,
Y
k
)
k
,各部屋の機密レベルが与えられたとき,見学者が 2 つの事務所であわせて
R
個以上の部屋を訪れることができるための,見学者の身分証の認証レベルの和の最小値を求めるプログラムを作成せよ.
なお,JOI 社が「ただ奇妙な発明」をすることでどうやって利益を得ているかは,社内でも最高機密であり社長以外の誰も知らない.
入力
入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．
1 行目には正整数 R (1 ≤
R
≤ 100000) が書かれている.2 行目以降には,2 つの事務所のデータが順に与えられる.
事務所のデータは,最初の行に正整数
W
k
,
H
k
,
X
k
,
Y
k
(1 ≤
X
k
≤
W
k
≤ 500, 1 ≤
Y
k
≤
H
k
≤ 500), 続く
H
k
行の
j
行目の
i
番目に, 部屋 (
i
,
j
)
k
の機密レベルを表す整数
L
k, i,j
(1 ≤
L
k,i,j
< 100000000 = 10
8
) として与えられる.
また,
R
≤
W
1
×
H
1
+
W
2
×
H
2
を満たす.
採点用データのうち, 配点の 30% 分については,
R
,
W
k
,
H
k
≤ 100 を満たす.
R
が 0 のとき入力の終了を示す.　データセットの数は 10 を超えない．
出力
データセットごとに,求める身分証の認証レベルの和の最小値を 1 行に出力する.
入出力例
入力例
5
2 2 1 2
9 5
1 17
3 2 2 1
6 1 20
8 18 3
8
5 4 1 3
5 5 4 5 5
8 2 1 9 7
1 1 3 5 1
7 2 7 1 3
6 5 6 2
2 3 5 8 2 7
1 6 9 4 5 1
2 4 5 4 2 2
5 4 2 5 3 3
7 1 5 1 5 6
6
3 3 2 2
2 9 2
9 1 9
2 9 2
2 2 1 1
1 3
5 7
0
出力例
15
4
9
1つ目の例 では,見学者に渡す身分証の認証レベルを,事務所 1 の認証レベルが 9,事務所 2 の認証レベルが 6 となるように設定すると,見学者は 5 個の部屋 (事務所 1 の部屋 (1, 1)
1
, (1, 2)
1
, (2, 1)
1
と,事務所 2 の部屋 (1, 1)
2
, (2, 1)
2
) を訪れることができる.このとき,認証レベルの和は 15 となる.これが合計 5 個以上の部屋を訪れることができるための認証レベルの和の最小値である.
３つ目の例 では,見学者に渡す身分証の認証レベルを,事務所 1 の認証レベルが 9,事務所 2 の認証レベルが 0 となるように設定すると,見学者は 9 個の部屋 (事務所 1 の部屋 (1, 1)
1
, (1, 2)
1
, (1, 3)
1
, (2, 1)
1
, (2, 2)
1
, (2, 3)
1
, (3, 1)
1
, (3, 2)
1
, (3, 3)
1
) を訪れることができる.事務所 2 の部屋は 1 個も訪れることができない.(エレベーターホール (1, 1)
2
にすら入ることができない.) このとき,認証レベルの和は 9 となる.これが合計 6 個以上の部屋を訪れることができるための認証レベルの和の最小値である.
上記問題文と自動審判に使われるデータは、
情報オリンピック日本委員会
が作成し公開している問題文と採点用テストデータです。

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
      
#define FOR(i,a,b) for( ll i = (a); i < (ll)(b); i++ )
#define REP(i,n) FOR(i,0,n)
#define YYS(x,arr) for(auto& x:arr)
#define ALL(x) (x).begin(),(x).end()
#define SORT(x) sort( (x).begin(),(x).end() )
#define REVERSE(x) reverse( (x).begin(),(x).end() )
#define UNIQUE(x) (x).erase( unique( ALL( (x) ) ) , (x).end() )
#define PW(x) (1LL<<(x))
#define SZ(x) ((ll)(x).size())
#define SHOW(x) cout << #x << " = " << x << endl
#define SHOWA(x,n) for( int yui = 0; yui < n; yui++ ){ cout << x[yui] << " "; } cout << endl

#define pb emplace_back
#define fi first
#define se second

using namespace std;

typedef long double ld;
typedef long long int ll;
typedef pair<int,int> pi;
typedef pair<ll,ll> pl;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<bool> vb;
typedef vector<ld> vd;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<vpl> gr;
typedef vector<vl> ml;
typedef vector<vd> md;
typedef vector<vi> mi;
     
const ll INF = (ll)1e9 + 10;
const ll INFLL = (ll)1e18 + 10;
const ld EPS = 1e-12;
const ll MOD = 1e9+7;
     
template<class T> T &chmin( T &a , const T &b ){ return a = min(a,b); }
template<class T> T &chmax( T &a , const T &b ){ return a = max(a,b); }
template<class T> inline T sq( T a ){ return a * a; }

ll in(){ long long int x; scanf( "%lld" , &x ); return x; }
char yuyushiki[1000010]; string stin(){ scanf( "%s" , yuyushiki ); return yuyushiki; }

// head

template<class T> pair<vi,vector<T> > compress( vector<T> a ){
  vector<T> ord = a;
  vi res(0);
  SORT( ord );
  UNIQUE( ord );
  YYS( w , a ) res.pb( lower_bound( ALL(ord) , w ) - ord.begin() );
  return make_pair( res , ord );
}

int w, h;
int a[510][510];
bool used[510][510];

const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, -1, 0, 1};

bool isin(int y, int x){
  return 0 <= y && y < h && 0 <= x && x < w;
}

using T = tuple<int, int, int>;

vi calc(){
  w = in();
  h = in();
  int x = in() - 1;
  int y = in() - 1;
  vi v(0);
  REP(i, h){
    REP(j, w){
      v.pb(in());
    }
  }
  auto c = compress(v);
  REP(i, h){
    REP(j, w){
      a[i][j] = c.fi[i*w+j];
    }
  }
  REP(i, h){
    REP(j, w){
      used[i][j] = false;
    }
  }
  vi res = {0};
  int cur = 0;
  priority_queue<T, vector<T>, greater<T> > que;
  que.emplace(a[y][x], y, x);
  used[y][x] = true;
  while(!que.empty()){
    int val, cy, cx;
    tie(val, cy, cx) = que.top();
    que.pop();
    chmax(cur, val);
    res.pb(c.se[cur]);
    REP(i, 4){
      int ny = cy + dy[i];
      int nx = cx + dx[i];
      if(isin(ny, nx) && !used[ny][nx]){
        used[ny][nx] = true;        
        que.emplace(a[ny][nx], ny, nx);
      }
    }
  }
  return res;
}

void solve(){
  int r = in();
  if(r == 0){
    exit(0);
  }
  vi resa = calc();
  vi resb = calc();
  /*
  SHOWA(resa, SZ(resa));
  SHOWA(resb, SZ(resb));
  */
  int ans = INF;
  REP(i, r+1){
    int j = r - i;
    if(i < SZ(resa) && j < SZ(resb)){
      chmin(ans, resa[i] + resb[j]);
    }
  }
  printf("%d\n", ans);
}

int main(){

  while(1){
    solve();
  }
  
  return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 12120
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
static constexpr int INF = 1<<28;
static constexpr int dr[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};

// R 本のクエリに対してそれぞれ最短の“最大値”経路を求める関数
// d: グリッドの高さ H, 幅 W の重みを格納した2D配列
// sx, sy: スタート位置 (0–based)
// out: 長さ R+1 のベクタ。 step i で到達可能な最小の“最大重み”を out[i] に格納
void dijkstra_maxmin(const vector<vector<int>>& d, int sx, int sy, vector<int>& out) {
    int H = d.size(), W = d[0].size(), R = out.size() - 1;
    // memo[y][x]: (y,x) に到達するまでの「最小の最大重み」
    static int memo[501][501];
    for (int y = 0; y < H; y++)
        for (int x = 0; x < W; x++)
            memo[y][x] = INF;

    // (cost, (x,y)), cost はこれまで通ったセル重みの最大値
    priority_queue< pair<int,pair<int,int>>,
                    vector<pair<int,pair<int,int>>>,
                    greater<> >
        pq;

    memo[sy][sx] = d[sy][sx];
    pq.emplace(d[sy][sx], pair{sx, sy});

    int step = 0;
    out[step++] = 0;  // 0 ステップ目はまだ何も踏んでいないので cost=0

    while (!pq.empty() && step <= R) {
        auto [cost, pos] = pq.top(); pq.pop();
        auto [x, y] = pos;
        if (cost != memo[y][x]) continue;
        out[step++] = cost;

        for (auto& mv : dr) {
            int nx = x + mv[0], ny = y + mv[1];
            if (nx < 0 || nx >= W || ny < 0 || ny >= H) continue;
            int ncost = max(cost, d[ny][nx]);
            if (ncost < memo[ny][nx]) {
                memo[ny][nx] = ncost;
                pq.emplace(ncost, pair{nx, ny});
            }
        }
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    while (true) {
        int R;
        cin >> R;
        if (!R) break;

        // 2 回分のクエリ情報を読み取り、各々について R+1 長の配列を得る
        vector<vector<int>> results(2, vector<int>(R+1, INF));
        for (int t = 0; t < 2; t++) {
            int W, H, X, Y;
            cin >> W >> H >> X >> Y;
            vector<vector<int>> d(H, vector<int>(W));
            for (int i = 0; i < H; i++) {
                for (int j = 0; j < W; j++) {
                    cin >> d[i][j];
                }
            }
            // 1-based の X,Y を 0-based に
            dijkstra_maxmin(d, X-1, Y-1, results[t]);
        }

        // 2 つのルートを i ステップと R−i ステップに分割して最適化
        int answer = INF;
        for (int i = 0; i <= R; i++) {
            answer = min(answer, results[0][i] + results[1][R - i]);
        }
        cout << answer << "\n";
    }

    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 6496
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;

vector<ll> calc(){ 
    ll W,H,X,Y;
    cin>>W>>H>>X>>Y;
    X--;Y--;
    vector<vector<ll>> A(H,vector<ll>(W));
    for(int h=0;h<H;h++){
        for(int w=0;w<W;w++)cin>>A[h][w];
    } 
    priority_queue<pair<ll,pair<ll,ll>>,vector<pair<ll,pair<ll,ll>>>,greater<pair<ll,pair<ll,ll>>>> Q;
    vector<ll> res(H*W+1,0);
    ll an=0;
    vector<ll> dx={-1,0,1,0},dy={0,1,0,-1}; 
    vector<vector<bool>> seen(H,vector<bool>(W,0));
    seen[Y][X]=1;
    Q.push({A[Y][X],{Y,X}});
    for(int i=0;i<H*W;i++){
        auto c=Q.top().first;
        auto [y,x]=Q.top().second;
        Q.pop();
        an=max(an,c);
        res[i+1]=an;
        for(int d=0;d<4;d++){
            ll ny=y+dy[d];
            ll nx=x+dx[d];
            if(ny<0||nx<0||ny>=H||nx>=W)continue;
            if(seen[ny][nx])continue;
            Q.push({A[ny][nx],{ny,nx}});
            seen[ny][nx]=1;
        }
    }
    return res;
}

int main() {
    ll R;
    while(cin>>R,R!=0){
    vector<ll> A=calc(),B=calc();
    ll an=1e18;
    for(int i=0;i<A.size();i++){
        int j=R-i;
        if(j>=B.size())continue;
        an=min(an,A[i]+B[j]);
    }
    cout<<an<<endl;
}
}
accuracy: 1
time_ms: 160
memory_kb: 10284
final_rank: 12

code_snippet: #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
#include <algorithm>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <vector>
#define repi(i,a,b) for(ll i=(a);i<(b);++i)
#define rep(i,a) repi(i,0,a)
#define repdi(i,a,b) for(ll i=(a)-1;i>=(b);--i)
#define repd(i,a) repdi(i,a,0)
#define itr(it,a) for( auto it = (a).begin(); it != (a).end(); ++it )
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define endl '\n'
#define debug(x) std::cerr << #x << " = " << (x) << endl;

using ll = long long;
using P = std::pair<ll, ll>;
using PP = std::pair<ll, P>;

constexpr ll INF = 1ll<<60;

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

template<class S, class T>
std::ostream& operator<< ( std::ostream& out, const std::pair<S,T>& a )
{ std::cout << '(' << a.first << ", " << a.second << ')'; return out; }

template<class T>
std::ostream &operator<< ( std::ostream& out, const std::vector<T>& a )
{ std::cout << '['; rep( i, a.size() ){ std::cout << a[i]; if( i != a.size()-1 ) std::cout << ", "; } std::cout << ']'; return out; }

ll R;
ll W[2], H[2], X[2], Y[2];
ll L[2][1000][1000];

const ll dx[4] = { -1, 0, 1, 0 }, dy[4] = { 0, 1, 0, -1 };

ll dist[2][1000][1000];

std::vector<ll> ds[2];

void dijkstra(ll i) {
    std::priority_queue<PP, std::vector<PP>, std::greater<PP>> pque;

    rep( j, W[i] ) rep( k, H[i] )
        dist[i][j][k] = INF;

    dist[i][X[i]][Y[i]] = 1;

    pque.emplace( dist[i][X[i]][Y[i]], P( X[i], Y[i] ) );

    while( !pque.empty() ) {
        PP p = pque.top(); pque.pop();
        ll d = p.first;
        ll x = p.second.first, y = p.second.second;

        if( d > dist[i][x][y] )
            continue;

        rep( dir, 4 ) {
            ll nx = x + dx[dir], ny = y + dy[dir];

            if (nx < 0 || nx >= W[i] || ny < 0 || ny >= H[i])
                continue;

            if( chmin( dist[i][nx][ny], std::max(d, L[i][nx][ny]) ) )
                pque.emplace( dist[i][nx][ny], P(nx, ny) );
        }
    }

    return;
}

int main() {
    while( std::cin >> R, R) {
        rep( i, 2 ) {
            std::cin >> W[i] >> H[i] >> X[i] >> Y[i];
            --X[i]; --Y[i];

            rep( j, H[i] ) {
                rep( k, W[i] ) {
                    std::cin >> L[i][k][j];
                }
            }
        }

        dijkstra(0);
        dijkstra(1);

        rep( i, 2 )
            ds[i].clear();

        rep( i, 2 ) rep( j, W[i] ) rep( k, H[i] ) {
            ds[i].emplace_back(dist[i][j][k]);
        }
        
        rep( i, 2 )
            std::sort(all(ds[i]));

        ll ans = INF;

        rep( i, ds[0].size() ) {
            ll l = ds[0][i];

            ll cnt0 = std::upper_bound(all(ds[0]), l) - ds[0].begin();
            
            if (R-cnt0 > 0 && R-cnt0-1 >= ds[1].size()) {
                continue;
            }

            ll l2 = R-cnt0 > 0 ? ds[1][R-cnt0-1] : 0;

            chmin( ans, l + l2 );
        }

        std::cout << ans << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 31132
final_rank: 19

code_snippet: #include <algorithm>
#include <cstdio>
#include <queue>
using namespace std;
void reader(int *x) {
  int k = getchar_unlocked();
  *x = k - '0';
  while (1) {
    k = getchar_unlocked();
    if (k < '0' || k > '9')
      break;
    *x = ((*x) << 1) + ((*x) << 3) + k - '0';
  }
}
struct state {
  int sx, sy, cost;
};
bool operator<(const state &s1, const state &s2) { return s1.cost < s2.cost; }
int R, H[2], W[2], sx[2], sy[2], a[2][509][509], cnt[2], b[2][250009];
bool vis[509][509];
int dir[] = {0, 1, 0, -1};
int main() {
  while (scanf("%d", &R), R) {
    for (int i = 0; i < 2; i++) {
      scanf("%d%d%d%d", &W[i], &H[i], &sy[i], &sx[i]);
      sy[i]--, sx[i]--;
      for (int j = 0; j < H[i]; j++) {
        for (int k = 0; k < W[i]; k++) {
          reader(&a[i][j][k]);
          vis[j][k] = false;
        }
      }
      priority_queue<state> que;
      que.push(state{sx[i], sy[i], -1});
      vis[sx[i]][sy[i]] = true;
      cnt[i] = 1;
      while (!que.empty()) {
        state u = que.top();
        que.pop();
        b[i][cnt[i]++] = a[i][u.sx][u.sy];
        for (int j = 0; j < 4; j++) {
          int tx = u.sx + dir[j], ty = u.sy + dir[j ^ 1];
          if (0 <= tx && tx < H[i] && 0 <= ty && ty < W[i] && !vis[tx][ty]) {
            a[i][tx][ty] = max(a[i][tx][ty], a[i][u.sx][u.sy]);
            vis[tx][ty] = true;
            que.push(state{tx, ty, -a[i][tx][ty]});
          }
        }
      }
    }
    int ret = 2000000009;
    for (int i = 0; i <= H[0] * W[0]; i++) {
      int z = max(R - i, 0);
      if (z > H[1] * W[1])
        continue;
      ret = min(ret, b[0][i] + b[1][z]);
    }
    printf("%d\n", ret);
  }
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 7184
final_rank: 6

code_snippet: #include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
void reader(int *x) {
  int k = getchar_unlocked();
  *x = k - '0';
  while (1) {
    k = getchar_unlocked();
    if (k < '0' || k > '9')
      break;
    *x = ((*x) << 1) + ((*x) << 3) + k - '0';
  }
}
struct state {
  int sx, sy, cost;
};
bool operator<(const state &s1, const state &s2) { return s1.cost < s2.cost; }
int R, H[2], W[2], sx[2], sy[2], a[2][509][509], cnt[2], b[2][250009];
bool vis[509][509];
int dir[] = {0, 1, 0, -1};
int main() {
  while (scanf("%d", &R), R) {
    for (int i = 0; i < 2; i++) {
      scanf("%d%d%d%d", &W[i], &H[i], &sy[i], &sx[i]);
      sy[i]--, sx[i]--;
      for (int j = 0; j < H[i]; j++) {
        for (int k = 0; k < W[i]; k++) {
          reader(&a[i][j][k]);
        }
      }
      priority_queue<state> que;
      que.push(state{sx[i], sy[i], -1});
      memset(vis, 0, sizeof(vis));
      vis[sx[i]][sy[i]] = true;
      cnt[i] = 1;
      while (!que.empty()) {
        state u = que.top();
        que.pop();
        b[i][cnt[i]++] = a[i][u.sx][u.sy];
        for (int j = 0; j < 4; j++) {
          int tx = u.sx + dir[j], ty = u.sy + dir[j ^ 1];
          if (0 <= tx && tx < H[i] && 0 <= ty && ty < W[i] && !vis[tx][ty]) {
            a[i][tx][ty] = max(a[i][tx][ty], a[i][u.sx][u.sy]);
            vis[tx][ty] = true;
            que.push(state{tx, ty, -a[i][tx][ty]});
          }
        }
      }
    }
    int ret = 2000000009;
    for (int i = 0; i <= H[0] * W[0]; i++) {
      int z = max(R - i, 0);
      if (z > H[1] * W[1])
        continue;
      ret = min(ret, b[0][i] + b[1][z]);
    }
    printf("%d\n", ret);
  }
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 7280
final_rank: 7

code_snippet: #include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define fst first
#define scd second
#define PB push_back
#define MP make_pair
#define all(a) a.begin(), a.end()
#define omajinai                                                               \
  ios::sync_with_stdio(false);                                                 \
  cin.tie(0)
#define rep(i, x) for (int i = 0; i < (int)(x); ++i)
typedef pair<int, int> pii;
typedef vector<pii> vpii;
template <typename T> bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
const int inf = 1e9;
int dy[] = {-1, 0, 1, 0};
int dx[] = {0, -1, 0, 1};
int R;
int W[2], H[2];
int X[2], Y[2];
int A[2][502][502];
bool used[502][502];
vpii data[2];
void bfs(int num) {
  typedef pair<int, pii> Data;
  memset(used, false, sizeof(used));
  priority_queue<Data> q;
  q.push(Data(-1, pii(Y[num], X[num])));
  used[Y[num]][X[num]] = true;
  if (num == 0) {
    data[num].PB(pii(1, 0));
  } else {
    data[num].PB(pii(0, 0));
    data[num].PB(pii(0, 1));
  }
  int ma = 1;
  int cnt = 0;
  int hoge = 0;
  while (q.size()) {
    Data p = q.top();
    q.pop();
    int cur = -p.fst;
    if (ma < cur) {
      if (num == 0) {
        data[num].back().scd = cnt;
      } else {
        data[num].back().fst = cnt;
      }
      ma = cur;
      if (num == 0) {
        data[num].PB(pii(ma, 0));
      } else {
        data[num].PB(pii(0, ma));
      }
    }
    cnt++;
    rep(i, 4) {
      int ny = p.scd.fst + dy[i], nx = p.scd.scd + dx[i];
      if (ny < 0 || ny >= H[num] || nx < 0 || nx >= W[num] || used[ny][nx])
        continue;
      used[ny][nx] = true;
      q.push(Data(-A[num][ny][nx], pii(ny, nx)));
    }
  }
  if (num == 0) {
    data[num].back().scd = cnt;
  } else {
    data[num].back().fst = cnt;
  }
}
signed main() {
  while (cin >> R, R) {
    data[0].clear();
    data[1].clear();
    rep(i, 2) {
      cin >> W[i] >> H[i] >> X[i] >> Y[i];
      --X[i], --Y[i];
      rep(j, H[i]) rep(k, W[i]) { cin >> A[i][j][k]; }
    }
    bfs(0);
    bfs(1);
    int mi = inf;
    data[1].PB(pii(inf, inf));
    rep(i, data[0].size()) {
      pii a = data[0][i];
      chmin(mi, a.fst + lower_bound(all(data[1]), pii(R - a.scd, -inf))->scd);
    }
    cout << mi << endl;
  }
}
accuracy: 1
time_ms: 200
memory_kb: 7624
final_rank: 16

code_snippet: #include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define fst first
#define scd second
#define PB push_back
#define all(a) a.begin(), a.end()
#define omajinai                                                               \
  ios::sync_with_stdio(false);                                                 \
  cin.tie(0)
#define rep(i, x) for (int i = 0; i < (int)(x); ++i)
typedef pair<int, int> pii;
typedef vector<pii> vpii;
template <typename T> bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
const int inf = 1e9;
int dy[] = {-1, 0, 1, 0};
int dx[] = {0, -1, 0, 1};
int R;
int W[2], H[2];
int X[2], Y[2];
int A[2][502][502];
bool used[502][502];
vpii data[2];
void bfs(int num) {
  typedef pair<int, pii> Data;
  memset(used, false, sizeof(used));
  priority_queue<Data> q;
  q.push(Data(-1, pii(Y[num], X[num])));
  used[Y[num]][X[num]] = true;
  if (num == 0) {
    data[num].PB(pii(1, 0));
  } else {
    data[num].PB(pii(0, 0));
    data[num].PB(pii(0, 1));
  }
  int ma = 1;
  int cnt = 0;
  int hoge = 0;
  while (q.size()) {
    Data p = q.top();
    q.pop();
    int cur = -p.fst;
    if (ma < cur) {
      if (num == 0) {
        data[num].back().scd = cnt;
      } else {
        data[num].back().fst = cnt;
      }
      ma = cur;
      if (num == 0) {
        data[num].PB(pii(ma, 0));
      } else {
        data[num].PB(pii(0, ma));
      }
    }
    cnt++;
    rep(i, 4) {
      int ny = p.scd.fst + dy[i], nx = p.scd.scd + dx[i];
      if (ny < 0 || ny >= H[num] || nx < 0 || nx >= W[num] || used[ny][nx])
        continue;
      used[ny][nx] = true;
      q.push(Data(-A[num][ny][nx], pii(ny, nx)));
    }
  }
  if (num == 0) {
    data[num].back().scd = cnt;
  } else {
    data[num].back().fst = cnt;
  }
}
signed main() {
  omajinai;
  while (cin >> R, R) {
    data[0].clear();
    data[1].clear();
    rep(i, 2) {
      cin >> W[i] >> H[i] >> X[i] >> Y[i];
      --X[i], --Y[i];
      rep(j, H[i]) rep(k, W[i]) { cin >> A[i][j][k]; }
    }
    bfs(0);
    bfs(1);
    int mi = inf;
    data[1].PB(pii(inf, inf));
    rep(i, data[0].size()) {
      pii a = data[0][i];
      chmin(mi, a.fst + lower_bound(all(data[1]), pii(R - a.scd, -inf))->scd);
    }
    cout << mi << endl;
  }
}
accuracy: 1
time_ms: 90
memory_kb: 7644
final_rank: 10

code_snippet: #include <algorithm>
#include <cstdio>
#include <queue>
#pragma warning(disable : 4996)
using namespace std;
struct state {
  int sx, sy, cost;
};
bool operator<(const state &s1, const state &s2) { return s1.cost < s2.cost; }
int R, H[2], W[2], sx[2], sy[2], a[2][509][509], cnt[2], b[2][250009];
bool vis[509][509];
int dir[] = {0, 1, 0, -1};
int main() {
  while (scanf("%d", &R), R) {
    for (int i = 0; i < 2; i++) {
      scanf("%d%d%d%d", &W[i], &H[i], &sy[i], &sx[i]);
      sy[i]--, sx[i]--;
      for (int j = 0; j < H[i]; j++) {
        for (int k = 0; k < W[i]; k++) {
          scanf("%d", &a[i][j][k]);
          vis[j][k] = false;
        }
      }
      priority_queue<state> que;
      que.push(state{sx[i], sy[i], -1});
      vis[sx[i]][sy[i]] = true;
      cnt[i] = 1;
      while (!que.empty()) {
        state u = que.top();
        que.pop();
        b[i][cnt[i]++] = a[i][u.sx][u.sy];
        for (int j = 0; j < 4; j++) {
          int tx = u.sx + dir[j], ty = u.sy + dir[j ^ 1];
          if (0 <= tx && tx < H[i] && 0 <= ty && ty < W[i] && !vis[tx][ty]) {
            a[i][tx][ty] = max(a[i][tx][ty], a[i][u.sx][u.sy]);
            vis[tx][ty] = true;
            que.push(state{tx, ty, -a[i][tx][ty]});
          }
        }
      }
    }
    int ret = 2000000009;
    for (int i = 0; i <= H[0] * W[0]; i++) {
      int z = max(R - i, 0);
      if (z > H[1] * W[1])
        continue;
      ret = min(ret, b[0][i] + b[1][z]);
    }
    printf("%d\n", ret);
  }
  return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 7352
final_rank: 9

code_snippet: #include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
#define f first
#define s second
#define mp make_pair
#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define rep(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOR(i, c)                                                              \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ALL(c) (c).begin(), (c).end()
#define IN(x, s, g) ((x) >= (s) && (x) < (g))
#define ISIN(x, y, w, h) (IN((x), 0, (w)) && IN((y), 0, (h)))
#define print(x) printf("%d\n", x)
using namespace std;
typedef unsigned int uint;
typedef long long ll;
const int _dx[] = {0, 1, 0, -1};
const int _dy[] = {-1, 0, 1, 0};
int getInt() {
  int ret = 0, c;
  c = getchar();
  while (!isdigit(c))
    c = getchar();
  while (isdigit(c)) {
    ret *= 10;
    ret += c - '0';
    c = getchar();
  }
  return ret;
}
int l[2][500][500];
bool c[2][500][500];
int memo[2][250001];
struct level {
  int l;
  int x;
  int y;
  level(int a, int b, int c) {
    l = a;
    x = b;
    y = c;
  }
};
bool operator<(const level &a, const level &b) { return a.l > b.l; }
int main() {
  int r;
  while (r = getInt()) {
    int w[2], h[2], x[2], y[2];
    REP(k, 2) {
      w[k] = getInt();
      h[k] = getInt();
      x[k] = getInt() - 1;
      y[k] = getInt() - 1;
      REP(i, h[k]) REP(j, w[k]) {
        l[k][i][j] = getInt();
        c[k][i][j] = false;
      }
      priority_queue<level> pq;
      pq.push(level(1, x[k], y[k]));
      c[k][y[k]][x[k]] = true;
      int cnt = 0;
      int now = 1;
      memo[k][cnt++] = 0;
      while (!pq.empty()) {
        level lv = pq.top();
        int ll = lv.l;
        int xx = lv.x;
        int yy = lv.y;
        pq.pop();
        memo[k][cnt++] = (now = max(ll, now));
        REP(i, 4) {
          int xxx = xx + _dx[i];
          int yyy = yy + _dy[i];
          if (ISIN(xxx, yyy, w[k], h[k]) && !c[k][yyy][xxx]) {
            c[k][yyy][xxx] = true;
            pq.push(level(l[k][yyy][xxx], xxx, yyy));
          }
        }
      }
    }
    int end = min(r, w[0] * h[0]) + 1;
    int start = max(0, r - w[1] * h[1]);
    int ans = INT_MAX;
    rep(i, start, end) ans = min(ans, memo[0][i] + memo[1][r - i]);
    print(ans);
  }
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 7640
final_rank: 8

code_snippet: #include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
#define f first
#define s second
#define mp make_pair
#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define rep(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOR(i, c)                                                              \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ALL(c) (c).begin(), (c).end()
#define IN(x, s, g) ((x) >= (s) && (x) < (g))
#define ISIN(x, y, w, h) (IN((x), 0, (w)) && IN((y), 0, (h)))
#define print(x) printf("%d\n", x)
using namespace std;
typedef unsigned int uint;
typedef long long ll;
const int _dx[] = {0, 1, 0, -1};
const int _dy[] = {-1, 0, 1, 0};
int getInt() {
  int ret = 0, c;
  c = getchar();
  while (!isdigit(c))
    c = getchar();
  while (isdigit(c)) {
    ret *= 10;
    ret += c - '0';
    c = getchar();
  }
  return ret;
}
int l[2][500][500];
bool c[2][500][500];
int memo[2][250001];
struct level {
  int l;
  int x;
  int y;
  level(int a, int b, int c) {
    l = a;
    x = b;
    y = c;
  }
};
bool operator<(const level &a, const level &b) { return a.l > b.l; }
int main() {
  int r;
  while (r = getInt()) {
    int w[2], h[2], x[2], y[2];
    REP(k, 2) {
      w[k] = getInt();
      h[k] = getInt();
      x[k] = getInt() - 1;
      y[k] = getInt() - 1;
      REP(i, h[k]) REP(j, w[k]) {
        l[k][i][j] = getInt();
        c[k][i][j] = false;
      }
      priority_queue<level> pq;
      pq.push(level(1, x[k], y[k]));
      c[k][y[k]][x[k]] = true;
      int cnt = 0;
      int now = 1;
      memo[k][cnt++] = 0;
      while (!pq.empty()) {
        level lv = pq.top();
        int ll = lv.l;
        int xx = lv.x;
        int yy = lv.y;
        pq.pop();
        memo[k][cnt++] = (now = max(ll, now));
        if (cnt == r + 1)
          break;
        REP(i, 4) {
          int xxx = xx + _dx[i];
          int yyy = yy + _dy[i];
          if (ISIN(xxx, yyy, w[k], h[k]) && !c[k][yyy][xxx]) {
            c[k][yyy][xxx] = true;
            pq.push(level(l[k][yyy][xxx], xxx, yyy));
          }
        }
      }
    }
    int end = min(r, w[0] * h[0]) + 1;
    int start = max(0, r - w[1] * h[1]);
    int ans = INT_MAX;
    rep(i, start, end) ans = min(ans, memo[0][i] + memo[1][r - i]);
    print(ans);
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 6472
final_rank: 2

code_snippet: #include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)n; ++i)
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
struct P {
  int d;
  int x, y;
  P(int d, int x, int y) : d(d), x(x), y(y) {}
};
bool operator<(const P &a, const P &b) { return a.d > b.d; }
int main() {
  int r;
  while (cin >> r, r) {
    int w[2], h[2], sx[2], sy[2];
    int ba[2][500][500];
    rep(k, 2) {
      cin >> w[k] >> h[k] >> sx[k] >> sy[k];
      sx[k]--;
      sy[k]--;
      rep(y, h[k]) rep(x, w[k]) cin >> ba[k][x][y];
    }
    int table[2][250001];
    rep(k, 2) {
      priority_queue<P> Q;
      Q.push(P(1, sx[k], sy[k]));
      bool visited[w[k]][h[k]];
      memset(visited, 0, sizeof(visited));
      int nowd = 0;
      int cnt = 0;
      while (!Q.empty()) {
        P p = Q.top();
        int x = p.x;
        int y = p.y;
        Q.pop();
        if (visited[x][y])
          continue;
        nowd = max(nowd, p.d);
        table[k][++cnt] = nowd;
        visited[x][y] = 1;
        rep(i, 4) {
          int xx = x + dx[i];
          int yy = y + dy[i];
          if (xx < 0 || xx >= w[k] || yy < 0 || yy >= h[k])
            continue;
          if (visited[xx][yy])
            continue;
          Q.push(P(ba[k][xx][yy], xx, yy));
        }
      }
    }
    int res = 1 << 29;
    for (int i = 0; i <= r; ++i) {
      if (i > w[0] * h[0] || r - i > w[1] * h[1])
        continue;
      res = min(res, table[0][i] + table[1][r - i]);
    }
    cout << res << endl;
  }
}
accuracy: 1
time_ms: 250
memory_kb: 8440
final_rank: 17

code_snippet: #include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)n; ++i)
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
struct P {
  int d;
  int x, y;
  P(int d, int x, int y) : d(d), x(x), y(y) {}
};
bool operator<(const P &a, const P &b) { return a.d > b.d; }
int main() {
  int r;
  while (cin >> r, r) {
    int w[2], h[2], sx[2], sy[2];
    int ba[2][500][500];
    rep(k, 2) {
      cin >> w[k] >> h[k] >> sx[k] >> sy[k];
      sx[k]--;
      sy[k]--;
      rep(y, h[k]) rep(x, w[k]) cin >> ba[k][x][y];
    }
    int table[2][250001];
    rep(k, 2) {
      priority_queue<P> Q;
      Q.push(P(1, sx[k], sy[k]));
      bool visited[w[k]][h[k]];
      memset(visited, 0, sizeof(visited));
      int nowd = 0;
      int cnt = 0;
      while (!Q.empty()) {
        P p = Q.top();
        int x = p.x;
        int y = p.y;
        Q.pop();
        if (visited[x][y])
          continue;
        nowd = max(nowd, p.d);
        table[k][++cnt] = nowd;
        if (cnt >= r)
          break;
        visited[x][y] = 1;
        rep(i, 4) {
          int xx = x + dx[i];
          int yy = y + dy[i];
          if (xx < 0 || xx >= w[k] || yy < 0 || yy >= h[k])
            continue;
          if (visited[xx][yy])
            continue;
          Q.push(P(ba[k][xx][yy], xx, yy));
        }
      }
    }
    int res = 1 << 29;
    for (int i = 0; i <= r; ++i) {
      if (i > w[0] * h[0] || r - i > w[1] * h[1])
        continue;
      res = min(res, table[0][i] + table[1][r - i]);
    }
    cout << res << endl;
  }
}
accuracy: 1
time_ms: 180
memory_kb: 6452
final_rank: 13

code_snippet: #include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
void reader(int *x) {
  int k = getchar_unlocked();
  *x = k - '0';
  while (1) {
    k = getchar_unlocked();
    if (k < '0' || k > '9')
      break;
    *x = ((*x) << 1) + ((*x) << 3) + k - '0';
  }
}
struct state {
  int sx, sy, cost;
};
bool operator<(const state &s1, const state &s2) { return s1.cost < s2.cost; }
int R, H[2], W[2], sx[2], sy[2], a[2][509][509], cnt[2], b[2][250009],
    vis[509][36];
int dir[] = {0, 1, 0, -1};
int main() {
  while (scanf("%d", &R), R) {
    for (int i = 0; i < 2; i++) {
      scanf("%d%d%d%d", &W[i], &H[i], &sy[i], &sx[i]);
      sy[i]--, sx[i]--;
      for (int j = 0; j < H[i]; j++) {
        for (int k = 0; k < W[i]; k++) {
          reader(&a[i][j][k]);
        }
      }
      priority_queue<state> que;
      que.push(state{sx[i], sy[i], -1});
      memset(vis, 0, sizeof(vis));
      vis[sx[i]][sy[i] >> 5] |= 1 << (sy[i] & 31);
      cnt[i] = 1;
      while (!que.empty()) {
        state u = que.top();
        que.pop();
        b[i][cnt[i]++] = a[i][u.sx][u.sy];
        for (int j = 0; j < 4; j++) {
          int tx = u.sx + dir[j], ty = u.sy + dir[j ^ 1];
          if (0 <= tx && tx < H[i] && 0 <= ty && ty < W[i] &&
              !(vis[tx][ty >> 5] & (1 << (ty & 31)))) {
            a[i][tx][ty] = max(a[i][tx][ty], a[i][u.sx][u.sy]);
            vis[tx][ty >> 5] |= 1 << (ty & 31);
            que.push(state{tx, ty, -a[i][tx][ty]});
          }
        }
      }
    }
    int ret = 2000000009;
    for (int i = 0; i <= H[0] * W[0]; i++) {
      int z = max(R - i, 0);
      if (z > H[1] * W[1])
        continue;
      ret = min(ret, b[0][i] + b[1][z]);
    }
    printf("%d\n", ret);
  }
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 7080
final_rank: 5

code_snippet: #include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
void reader(int *x) {
  int k = getchar_unlocked();
  *x = k - '0';
  while (1) {
    k = getchar_unlocked();
    if (k < '0' || k > '9')
      break;
    *x = ((*x) << 1) + ((*x) << 3) + k - '0';
  }
}
struct state {
  int sx, sy, cost;
};
bool operator<(const state &s1, const state &s2) { return s1.cost < s2.cost; }
int R, H[2], W[2], sx[2], sy[2], a[2][509][509], cnt[2], b[2][250009],
    vis[509][36];
int dir[] = {0, 1, 0, -1};
int main() {
  while (scanf("%d", &R), R) {
    for (int i = 0; i < 2; i++) {
      scanf("%d%d%d%d", &W[i], &H[i], &sy[i], &sx[i]);
      sy[i]--, sx[i]--;
      for (int j = 0; j < H[i]; j++) {
        for (int k = 0; k < W[i]; k++) {
          reader(&a[i][j][k]);
        }
      }
      priority_queue<state> que;
      que.push(state{sx[i], sy[i], -1});
      memset(vis, 0, sizeof(vis));
      vis[sx[i]][sy[i] >> 5] |= 1 << (sy[i] & 31);
      cnt[i] = 1;
      while (!que.empty()) {
        state u = que.top();
        que.pop();
        b[i][cnt[i]++] = a[i][u.sx][u.sy];
        if (cnt[i] > R)
          break;
        for (int j = 0; j < 4; j++) {
          int tx = u.sx + dir[j], ty = u.sy + dir[j ^ 1];
          if (0 <= tx && tx < H[i] && 0 <= ty && ty < W[i] &&
              !(vis[tx][ty >> 5] & (1 << (ty & 31)))) {
            a[i][tx][ty] = max(a[i][tx][ty], a[i][u.sx][u.sy]);
            vis[tx][ty >> 5] |= 1 << (ty & 31);
            que.push(state{tx, ty, -a[i][tx][ty]});
          }
        }
      }
    }
    int ret = 2000000009;
    for (int i = 0; i <= R && i <= H[0] * W[0]; i++) {
      int z = max(R - i, 0);
      if (z > H[1] * W[1])
        continue;
      ret = min(ret, b[0][i] + b[1][z]);
    }
    printf("%d\n", ret);
  }
  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 5768
final_rank: 1

code_snippet: #include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define fst first
#define scd second
#define PB push_back
#define all(a) a.begin(), a.end()
#define omajinai                                                               \
  ios::sync_with_stdio(false);                                                 \
  cin.tie(0)
#define rep(i, x) for (int i = 0; i < (int)(x); ++i)
typedef pair<int, int> pii;
typedef vector<pii> vpii;
template <typename T> bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
const int inf = 1e9;
int dy[] = {-1, 0, 1, 0};
int dx[] = {0, -1, 0, 1};
int R;
int W[2], H[2];
int X[2], Y[2];
int A[2][502][502];
bool used[502][502];
vpii data[2];
void bfs(int num) {
  typedef pair<int, pii> Data;
  memset(used, false, sizeof(used));
  priority_queue<Data> q;
  q.push(Data(-1, pii(Y[num], X[num])));
  used[Y[num]][X[num]] = true;
  if (num == 0) {
    data[num].PB(pii(1, 0));
  } else {
    data[num].PB(pii(0, 0));
    data[num].PB(pii(0, 1));
  }
  int ma = 1;
  int cnt = 0;
  while (q.size()) {
    Data p = q.top();
    q.pop();
    int cur = -p.fst;
    if (ma < cur) {
      if (num == 0) {
        data[num].back().scd = cnt;
        ma = cur;
        data[num].PB(pii(ma, 0));
      } else {
        data[num].back().fst = cnt;
        ma = cur;
        data[num].PB(pii(0, ma));
      }
    }
    cnt++;
    rep(i, 4) {
      int ny = p.scd.fst + dy[i], nx = p.scd.scd + dx[i];
      if (ny < 0 || ny >= H[num] || nx < 0 || nx >= W[num] || used[ny][nx])
        continue;
      used[ny][nx] = true;
      q.push(Data(-A[num][ny][nx], pii(ny, nx)));
    }
  }
  if (num == 0) {
    data[num].back().scd = cnt;
  } else {
    data[num].back().fst = cnt;
  }
}
signed main() {
  while (cin >> R, R) {
    data[0].clear();
    data[1].clear();
    rep(i, 2) {
      cin >> W[i] >> H[i] >> X[i] >> Y[i];
      --X[i], --Y[i];
      rep(j, H[i]) rep(k, W[i]) { cin >> A[i][j][k]; }
    }
    bfs(0);
    bfs(1);
    int mi = inf;
    data[1].PB(pii(inf, inf));
    rep(i, data[0].size()) {
      pii a = data[0][i];
      chmin(mi, a.fst + lower_bound(all(data[1]), pii(R - a.scd, -inf))->scd);
    }
    cout << mi << endl;
  }
}
accuracy: 1
time_ms: 190
memory_kb: 7552
final_rank: 15

code_snippet: #include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define fst first
#define scd second
#define PB push_back
#define all(a) a.begin(), a.end()
#define omajinai                                                               \
  ios::sync_with_stdio(false);                                                 \
  cin.tie(0)
#define rep(i, x) for (int i = 0; i < (int)(x); ++i)
typedef pair<int, int> pii;
typedef vector<pii> vpii;
template <typename T> bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
const int inf = 1e9;
int dy[] = {-1, 0, 1, 0};
int dx[] = {0, -1, 0, 1};
int R;
int W[2], H[2];
int X[2], Y[2];
int A[2][502][502];
bool used[502][502];
vpii data[2];
void bfs(int num) {
  typedef pair<int, pii> Data;
  memset(used, false, sizeof(used));
  priority_queue<Data> q;
  q.push(Data(-1, pii(Y[num], X[num])));
  used[Y[num]][X[num]] = true;
  if (num == 0) {
    data[num].PB(pii(1, 0));
  } else {
    data[num].PB(pii(0, 0));
    data[num].PB(pii(0, 1));
  }
  int ma = 1;
  int cnt = 0;
  while (q.size()) {
    Data p = q.top();
    q.pop();
    int cur = -p.fst;
    if (ma < cur) {
      if (num == 0) {
        data[num].back().scd = cnt;
        ma = cur;
        data[num].PB(pii(ma, 0));
      } else {
        data[num].back().fst = cnt;
        ma = cur;
        data[num].PB(pii(0, ma));
      }
    }
    cnt++;
    rep(i, 4) {
      int ny = p.scd.fst + dy[i], nx = p.scd.scd + dx[i];
      if (ny < 0 || ny >= H[num] || nx < 0 || nx >= W[num] || used[ny][nx])
        continue;
      used[ny][nx] = true;
      q.push(Data(-A[num][ny][nx], pii(ny, nx)));
    }
  }
  if (num == 0) {
    data[num].back().scd = cnt;
  } else {
    data[num].back().fst = cnt;
  }
}
signed main() {
  omajinai;
  while (cin >> R, R) {
    data[0].clear();
    data[1].clear();
    rep(i, 2) {
      cin >> W[i] >> H[i] >> X[i] >> Y[i];
      --X[i], --Y[i];
      rep(j, H[i]) rep(k, W[i]) { cin >> A[i][j][k]; }
    }
    bfs(0);
    bfs(1);
    int mi = inf;
    data[1].PB(pii(inf, inf));
    rep(i, data[0].size()) {
      pii a = data[0][i];
      chmin(mi, a.fst + lower_bound(all(data[1]), pii(R - a.scd, -inf))->scd);
    }
    cout << mi << endl;
  }
}
accuracy: 1
time_ms: 90
memory_kb: 7692
final_rank: 11

code_snippet: #include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < n; i++)
using namespace std;
int ans[2][100001], w, h, x, y, f[500][500];
int dx[]{1, -1, 0, 0}, dy[]{0, 0, 1, -1};
bool used[500][500];
struct st {
  int x, y, c;
};
bool operator<(st a, st b) { return a.c > b.c; }
int main() {
  int r;
  while (scanf("%d", &r), r) {
    fill(ans[0], ans[2], INT_MAX);
    rep(i, 2) {
      memset(used, 0, sizeof(used));
      ans[i][0] = 0;
      scanf("%d%d%d%d", &w, &h, &y, &x);
      x--;
      y--;
      rep(j, h) rep(k, w) scanf("%d", &f[j][k]);
      priority_queue<st> que;
      que.push({x, y, 1});
      used[x][y] = true;
      int cnt = 0, Max = 0;
      while (!que.empty()) {
        st s = que.top();
        que.pop();
        cnt++;
        Max = max(Max, s.c);
        ans[i][cnt] = min(ans[i][cnt], Max);
        if (cnt >= r)
          break;
        rep(j, 4) {
          int nx = s.x + dx[j], ny = s.y + dy[j];
          if (0 <= nx && nx < h && 0 <= ny && ny < w && !used[nx][ny]) {
            used[nx][ny] = true;
            que.push({nx, ny, f[nx][ny]});
          }
        }
      }
      for (int j = r - 1; j > 0; j--)
        ans[i][j] = min(ans[i][j], ans[i][j + 1]);
    }
    int Min = INT_MAX;
    rep(i, r + 1) {
      if (ans[0][i] == INT_MAX || ans[1][r - i] == INT_MAX)
        continue;
      Min = min(Min, ans[0][i] + ans[1][r - i]);
    }
    printf("%d\n", Min);
  }
}
accuracy: 1
time_ms: 60
memory_kb: 5388
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <random>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i = 0; i < (n); i++)

template<class T>
using vi = vector<T>;

template<class T>
using vii = vector<vi<T>>;

template<class T>
using viii = vector<vii<T>>;

using tii = tuple<int, int, int>;
using pii = pair<int, int>;

int seclv[2][510][510];
int passlv[2][510][510];
const int dx[4] = { 1, 0, -1, 0 };
const int dy[4] = { 0, 1, 0, -1 };

int main()
{
    int r;
    while(cin >> r, r){
        vi<int> w(2), h(2), x(2), y(2);
        const int inf = 1e9;
        rep(idx, 2) {
            cin >> w[idx] >> h[idx] >> y[idx] >> x[idx];
            x[idx]--, y[idx]--;
            rep(i, h[idx]) rep(j, w[idx]) cin >> seclv[idx][i][j];
            rep(i, h[idx]) rep(j, w[idx]) passlv[idx][i][j] = inf;        
        }
    
        rep(idx, 2) {
            priority_queue<tii, vi<tii>, greater<tii>> pq;
            pq.push({ 1, x[idx], y[idx] });
            passlv[idx][x[idx]][y[idx]] = 1;
            int now = 1;
            int num, sx, sy;
            while (!pq.empty()) {
                tie(num, sx, sy) = pq.top();
                pq.pop();
                //cout << num << ' ' << sx << ' ' << sy << endl;
                if (passlv[idx][sx][sy] < num) continue;
                if (num > now) now = num;
                rep(i, 4) {
                    int nx = sx + dx[i];
                    int ny = sy + dy[i];
                    if (nx < 0 || nx >= h[idx] || ny < 0 || ny >= w[idx]) continue;
                    int tp = max(now, seclv[idx][nx][ny]);
                    if (passlv[idx][nx][ny] <= tp) continue;
                    passlv[idx][nx][ny] = tp;
                    pq.push({ tp, nx, ny });
                }
            }
        }
    
        vi<map<int, int>> mp(2);
        vii<pii> d(2);
        rep(idx, 2) {
            rep(i, h[idx]) rep(j, w[idx]) mp[idx][passlv[idx][i][j]]++;
    
            d[idx].push_back({ 0, 0 });
            for (auto elem : mp[idx]) {
                d[idx].push_back({ d[idx].back().first + elem.second, elem.first });
            }
        }
    
        int ans = inf;
        {
            int ld0 = d[0].size();
            int ld1 = d[1].size();
            int pos = 0; 
            for (int i = ld0 - 1; i >= 0; i--) {
                while (pos < ld1 && d[0][i].first + d[1][pos].first < r) pos++;
                if (pos == ld1) break;
                ans = min(ans, d[0][i].second + d[1][pos].second);            
            }
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 19668
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define drep(i,j,n) for(int i=0;i<(int)(n-1);i++)for(int j=i+1;j<(int)(n);j++)
#define trep(i,j,k,n) for(int i=0;i<(int)(n-2);i++)for(int j=i+1;j<(int)(n-1);j++)for(int k=j+1;k<(int)(n);k++)
#define codefor int test;scanf("%d",&test);while(test--)
#define INT(...) int __VA_ARGS__;in(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;in(__VA_ARGS__)
#define yes(ans) if(ans)printf("yes\n");else printf("no\n")
#define Yes(ans) if(ans)printf("Yes\n");else printf("No\n")
#define YES(ans) if(ans)printf("YES\n");else printf("NO\n")
#define popcount(v) __builtin_popcountll(v)
#define vector2d(type,name,h,...) vector<vector<type>>name(h,vector<type>(__VA_ARGS__))
#define vector3d(type,name,h,w,...) vector<vector<vector<type>>>name(h,vector<vector<type>>(w,vector<type>(__VA_ARGS__)))
#define vector4d(type,name,h,w,d,...) vector<vector<vector<vector<type>>>>name(h,vector<vector<vector<type>>>(w,vector<vector<type>>(d,vector<type>(__VA_ARGS__))))
using namespace std;
using ll = long long;
template<class T> using rpriority_queue = priority_queue<T, vector<T>, greater<T>>;
const int MOD=1000000007;
const int MOD2=998244353;
const int INF=1<<30;
const ll INF2=1LL<<60;
void scan(int& a){scanf("%d",&a);}
void scan(long long& a){scanf("%lld",&a);}
template<class T,class L>void scan(pair<T, L>& p){scan(p.first);scan(p.second);}
template<class T,class U,class V>void scan(tuple<T,U,V>& p){scan(get<0>(p));scan(get<1>(p));scan(get<2>(p));}
template<class T, size_t size> void scan(array<T, size>& a){ for(auto&& i : a) scan(i);}
template<class T> void scan(T& a){cin>>a;}
template<class T> void scan(vector<T>& vec){for(auto&& it:vec)scan(it);}
void in(){}
template <class Head, class... Tail> void in(Head& head, Tail&... tail){scan(head);in(tail...);}
void print(const int& a){printf("%d",a);}
void print(const long long& a){printf("%lld",a);}
void print(const double& a){printf("%.15lf",a);}
template<class T,class L>void print(const pair<T, L>& p){print(p.first);putchar(' ');print(p.second);}
template<class T> void print(const T& a){cout<<a;}
template<class T> void print(const vector<T>& vec){if(vec.empty())return;print(vec[0]);for(auto it=vec.begin();++it!= vec.end();){putchar(' ');print(*it);}}
void out(){putchar('\n');}
template<class T> void out(const T& t){print(t);putchar('\n');}
template <class Head, class... Tail> void out(const Head& head,const Tail&... tail){print(head);putchar(' ');out(tail...);}
template<class T> void dprint(const T& a){cerr<<a;}
template<class T> void dprint(const vector<T>& vec){if(vec.empty())return;cerr<<vec[0];for(auto it=vec.begin();++it!= vec.end();){cerr<<" "<<*it;}}
void debug(){cerr<<endl;}
template<class T> void debug(const T& t){dprint(t);cerr<<endl;}
template <class Head, class... Tail> void debug(const Head& head, const Tail&... tail){dprint(head);cerr<<" ";debug(tail...);}
ll intpow(ll a, ll b){ ll ans = 1; while(b){ if(b & 1) ans *= a; a *= a; b /= 2; } return ans; }
ll modpow(ll a, ll b, ll p){ ll ans = 1; while(b){ if(b & 1) (ans *= a) %= p; (a *= a) %= p; b /= 2; } return ans; }
ll modinv(ll a, ll m) {ll b = m, u = 1, v = 0;while (b) {ll t = a / b;a -= t * b; swap(a, b);u -= t * v; swap(u, v);}u %= m;if (u < 0) u += m;return u;}
ll updivide(ll a,ll b){return (a+b-1)/b;}
int msb(ll v){return 63-__builtin_clzll(v);}
template<class T> void chmax(T &a,const T b){if(b>a)a=b;}
template<class T> void chmin(T &a,const T b){if(b<a)a=b;}

template<class T> struct compressed_array{
    int N;
    vector<T> dat;
    const T operator[](int i) const { return dat[i]; }
    T operator[](int i) { return dat[i]; }
    compressed_array(){}
    compressed_array(vector<int> &a){
        dat=a;
    }
    void build(){
        sort(dat.begin(), dat.end());
        dat.erase(unique(dat.begin(), dat.end()), dat.end());
        N = dat.size();
    }
    int size(){return N;}
    void insert(const T v){
        dat.push_back(v);
    }
    void insert(vector<T> &a){
        for(int i = 0; i < a.size() ; i++)dat.push_back(a[i]);
    }
    //type1でfirst,type2でsecond
    void insert(vector<pair<T, T>> &a, int type){
        if(type==1){
            for(int i = 0; i < a.size(); i++)dat.push_back(a[i].first);
        }else{
            for(int i = 0; i < a.size(); i++)dat.push_back(a[i].second);
        }
    }
    template<size_t size> void insert(vector<array<T,size>> &a, int pos){
        assert(0 <= pos && pos < size);
        for(int i = 0; i < a.size() ; i++){
            dat.push_back(a[i][pos]);
        }
    }
    int load(T &v){
        return lower_bound(dat.begin(), dat.end(), v) - dat.begin();
    }
    void load(vector<T> &a){
        for(int i = 0; i < a.size() ; i++)a[i] = load(a[i]);
    }
    void load(vector<pair<T, T>> &a, int type){
        if(type==1){
            for(int i = 0; i < a.size(); i++)a[i].first = load(a[i].first);
        }else{
            for(int i = 0; i < a.size(); i++)a[i].second = load(a[i].second);
        }
    }
    template<size_t size> void load(vector<array<T,size>> &a, int pos){
        assert(0 <= pos && pos < size);
        for(int i = 0; i < a.size() ; i++){
            a[i][pos] = load(a[i][pos]);
        }
    }
};

struct dsu {
  public:
    dsu() : _n(0) {}
    dsu(int n) : _n(n), parent_or_size(n, -1) {}

    int merge(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        int x = leader(a), y = leader(b);
        if (x == y) return x;
        if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
        parent_or_size[x] += parent_or_size[y];
        parent_or_size[y] = x;
        return x;
    }

    bool same(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        return leader(a) == leader(b);
    }

    int leader(int a) {
        assert(0 <= a && a < _n);
        if (parent_or_size[a] < 0) return a;
        return parent_or_size[a] = leader(parent_or_size[a]);
    }

    int size(int a) {
        assert(0 <= a && a < _n);
        return -parent_or_size[leader(a)];
    }

    std::vector<std::vector<int>> groups() {
        std::vector<int> leader_buf(_n), group_size(_n);
        for (int i = 0; i < _n; i++) {
            leader_buf[i] = leader(i);
            group_size[leader_buf[i]]++;
        }
        std::vector<std::vector<int>> result(_n);
        for (int i = 0; i < _n; i++) {
            result[i].reserve(group_size[i]);
        }
        for (int i = 0; i < _n; i++) {
            result[leader_buf[i]].push_back(i);
        }
        result.erase(
            std::remove_if(result.begin(), result.end(),
                           [&](const std::vector<int>& v) { return v.empty(); }),
            result.end());
        return result;
    }

  private:
    int _n;
    // root node: -1 * component size
    // otherwise: parent
    std::vector<int> parent_or_size;
};

int main(){
    while(1){
    INT(R);
    if(!R)return 0;
    INT(w1,h1,x1,y1);
    compressed_array<int> ca;
    vector2d(int,A,h1,w1);
    in(A);
    INT(w2,h2,x2,y2);
    vector2d(int,B,h2,w2);
    in(B);
    x1--,y1--,x2--,y2--;
    vector<int> t1(h1*w1+1,INF),t2(h2*w2+1,INF);
    vector2d(bool,used1,h1,w1,false);
    vector2d(bool,used2,h2,w2,false);
    rep(y,h1)ca.insert(A[y]);
    rep(y,h2)ca.insert(B[y]);
    ca.build();
    vector<vector<pair<int,int>>> At(ca.size()),Bt(ca.size());
    rep(y,h1){
        ca.load(A[y]);
        rep(x,w1)At[A[y][x]].emplace_back(y,x);
    }
    rep(y,h2){
        ca.load(B[y]);
        rep(x,w2)Bt[B[y][x]].emplace_back(y,x);
    }
    dsu uf1(h1*w1),uf2(h2*w2);
    for(int i=0,y,x;i<ca.size();i++){
        for(auto p:At[i]){
            tie(y,x)=p;
            used1[y][x]=true;
            for(int j=0;j<4;j++){
                int dy=(j==0)-(j==1);
                int dx=(j==2)-(j==3);
                if(y+dy<0||x+dx<0||y+dy>=h1||x+dx>=w1)continue;
                if(!used1[y+dy][x+dx])continue;
                uf1.merge(y*w1+x,(y+dy)*w1+x+dx);
            }
        }
        chmin(t1[uf1.size(y1*w1+x1)],ca[i]);
        for(auto p:Bt[i]){
            tie(y,x)=p;
            used2[y][x]=true;
            for(int j=0;j<4;j++){
                int dy=(j==0)-(j==1);
                int dx=(j==2)-(j==3);
                if(y+dy<0||x+dx<0||y+dy>=h2||x+dx>=w2)continue;
                if(!used2[y+dy][x+dx])continue;
                uf2.merge(y*w2+x,(y+dy)*w2+x+dx);
            }
        }
        chmin(t2[uf2.size(y2*w2+x2)],ca[i]);
    }
    t1[0]=0,t2[0]=0;
    for(int i=h1*w1;i>=1;i--)chmin(t1[i-1],t1[i]);
    for(int i=h2*w2;i>=1;i--)chmin(t2[i-1],t2[i]);
    //debug(t1);
    //debug(t2);
    int ans=INF;
    for(int i=0;i<=h1*w1;i++){
        int j=R-i;
        if(j>h2*w2||j<0)continue;
        chmin(ans,t1[i]+t2[j]);
    }
    out(ans);
    }
}
accuracy: 1
time_ms: 220
memory_kb: 50096
final_rank: 20