#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<deque>
#include<iomanip>
#include<tuple>
#include<cassert>
#include<set>
#include<complex>
#include<numeric>
#include<functional>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long int LL;
typedef pair<int,int> P;
typedef pair<LL,LL> LP;
const int INF=1<<30;
const LL MAX=1e9+7;

void array_show(int *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%d%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(LL *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%lld%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(vector<int> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%d%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
void array_show(vector<LL> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%lld%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
template<typename T> ostream& operator<<(ostream& os,const vector<T>& v1){
    int n=v1.size();
    for(int i=0;i<n;i++){
        if(i)os<<" ";
        os<<v1[i];
    }
    return os;
}
template<typename T1,typename T2> ostream& operator<<(ostream& os,const pair<T1,T2>& p){
    os<<p.first<<" "<<p.second;
    return os;
}
template<typename T> istream& operator>>(istream& is,vector<T>& v1){
    int n=v1.size();
    for(int i=0;i<n;i++)is>>v1[i];
    return is;
}

namespace sol{

    int n,m;
    vector<vector<int>> grid;

    bool check(int g){
        int i,j,k;
        int a,b,c;
        vector<vector<int>> v1(n+2,vector<int>(n+2,0));
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                if(grid[i][j]<=g)v1[i+1][j+1]=1;
            }
        }
        for(i=0;i<=n;i++){
            for(j=0;j<=n;j++){
                if(i)v1[i][j]+=v1[i-1][j];
                if(j)v1[i][j]+=v1[i][j-1];
                if(i && j)v1[i][j]-=v1[i-1][j-1];
            }
        }
        for(i=0;i<=n-m;i++){
            for(j=0;j<=n-m;j++){
                a=v1[i+m][j+m]+v1[i][j]-v1[i][j+m]-v1[i+m][j];
                if(a>=(m*m+1)/2)return true;
            }
        }
        return false;
    }

    void solve(){
        int i,j,k;
        int a,b,c;
        cin>>n>>m;
        grid.assign(n,vector<int>(n));
        cin>>grid;
        int z[3]={-1,INF};
        while(z[1]-z[0]>1){
            z[2]=(z[0]+z[1])/2;
            if(check(z[2]))z[1]=z[2];
            else z[0]=z[2];
        }
        cout<<z[1]<<endl;
    }
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    sol::solve();
}
#include <bits/stdc++.h>
using namespace std;

const int MAX_LEN = 50;
string DIR[4] = {"U", "D", "L", "R"};

int depth;

int si, sj;
int t[MAX_LEN][MAX_LEN], p[MAX_LEN][MAX_LEN];



int next_sim(int i, int j, bool visited[], int num) {
  if ( num == 0 ) { return p[i][j]; }

  bool *now_visited;
  now_visited = new bool[2500];
  memcpy(now_visited, visited, sizeof(visited));
  now_visited[t[i][j]] = true;

  int sim_p = 0;

  if ( i > 0 && (! visited[t[i-1][j]]) && p[i-1][j] > sim_p ) {
    int tmp = next_sim(i-1, j, now_visited, num-1);
    if ( tmp > sim_p ) { sim_p = tmp; }
  }
  if ( i < MAX_LEN-1 && (! visited[t[i+1][j]]) && p[i+1][j] > sim_p ) {
    int tmp = next_sim(i+1, j, now_visited, num-1);
    if ( tmp > sim_p ) { sim_p = tmp; }
  }
  if ( j > 0 && (! visited[t[i][j-1]]) && p[i][j-1] > sim_p ) {
    int tmp = next_sim(i, j-1, now_visited, num-1);
    if ( tmp > sim_p ) { sim_p = tmp; }
  }
  if ( j < MAX_LEN-1 && (! visited[t[i][j+1]]) && p[i][j+1] > sim_p ) {
    int tmp = next_sim(i, j+1, now_visited, num-1);
    if ( tmp > sim_p ) { sim_p = tmp; }
  }

  delete[] now_visited;
  return p[i][j] + sim_p;
}

int sakiyomi(int i, int j, bool visited[]) {
  int sim_p = next_sim(i, j, visited, depth);

  return sim_p;
}

int next_dir(int i, int j, bool visited[]) {
  int ret  = 4;
  int sim_p = -1;

  int sim_i, sim_j;

  if ( i > 0 && (! visited[t[i-1][j]]) ) {
    int tmp = sakiyomi(i-1, j, visited);
    if ( tmp > sim_p ) { ret = 0; sim_p = tmp; }
  }
  if ( i < MAX_LEN-1 && (! visited[t[i+1][j]]) ) {
    int tmp = sakiyomi(i+1, j, visited);
    if ( tmp > sim_p ) { ret = 1; sim_p = tmp; }
  }
  if ( j > 0 && (! visited[t[i][j-1]]) ) {
    int tmp = sakiyomi(i, j-1, visited);
    if ( tmp > sim_p ) { ret = 2; sim_p = tmp; }
  }
  if ( j < MAX_LEN-1 && (! visited[t[i][j+1]]) ) {
    int tmp = sakiyomi(i, j+1, visited);
    if ( tmp > sim_p ) { ret = 3; sim_p = tmp; }
  }

  return ret;
}

void update_pos(int* i, int* j, int next) {
  if ( next == 0 ) { *i -= 1; }
  if ( next == 1 ) { *i += 1; }
  if ( next == 2 ) { *j -= 1; }
  if ( next == 3 ) { *j += 1; }
}

string calc() {
  string ans = "";
  int max_p = p[si][sj];
  
  for ( depth = 0 ; depth < 3; depth++ ) {
    bool visited[2500] = {};
    string now_ans = "";
    int point = 0;

    int i = si;
    int j = sj;
    visited[t[i][j]] = true;
    point = p[i][j];

    while ( true ) {
      int next = next_dir(i, j, visited);
      if ( next == 4 ) { break; }
      now_ans += DIR[next];
      update_pos(&i, &j, next);
      visited[t[i][j]] = true;
      point += p[i][j];
    }

    if ( point > max_p ) {
      max_p = point;
      ans = now_ans;
    }
  }

  return ans;
}

int main() {
  cin >> si >> sj;

  for ( int i = 0; i < MAX_LEN; i++ ) {
    for ( int j = 0; j < MAX_LEN; j++ ) {
      cin >> t[i][j];
    }
  }
  for ( int i = 0; i < MAX_LEN; i++ ) {
    for ( int j = 0; j < MAX_LEN; j++ ) {
      cin >> p[i][j];
    }
  }

  cout << calc() << endl;
  return 0;
}
