#include <bits/stdc++.h>
using namespace std;
const int MAXN = 300;
const int ROOM = -1;
const int REAC = -2;
const int BAD_REAC = -3;
const int CAPS = ROOM;
class Aresta {
 public:
  int to, rev, flow, cap;
  Aresta() {}
  Aresta(int _to, int _rev, int _flow, int _cap) {
    to = _to;
    rev = _rev;
    flow = _flow;
    cap = _cap;
  }
};
class Dinic {
 public:
  int nodes, *level, *q, *work;
  vector<Aresta *> *grafo;
  Dinic(int tam) {
    nodes = tam;
    level = new int[nodes];
    q = new int[nodes];
    work = new int[nodes];
    grafo = new vector<Aresta *>[nodes];
  }
  void limpa() {
    for (int i = 0; i < nodes; i++) {
      for (size_t j = 0; j < grafo[i].size(); j++) {
        delete grafo[i][j];
      }
      grafo[i].clear();
    }
  }
  void destroy() {
    limpa();
    delete level;
    delete q;
    delete work;
    delete grafo;
  }
  void add(int s, int t, int cap) {
    Aresta *a = new Aresta(t, grafo[t].size(), 0, cap);
    Aresta *b = new Aresta(s, grafo[s].size(), 0, 0);
    grafo[s].push_back(a);
    grafo[t].push_back(b);
  }
  void undirectedAdd(int s, int t, int cap) {
    Aresta *a = new Aresta(t, grafo[t].size(), 0, cap);
    Aresta *b = new Aresta(s, grafo[s].size(), 0, cap);
    grafo[s].push_back(a);
    grafo[t].push_back(b);
  }
  bool bfs(int source, int sink) {
    for (int i = 0; i < nodes; i++) {
      level[i] = -1;
    }
    queue<int> fila;
    level[source] = 0;
    fila.push(source);
    int atual;
    while (!fila.empty()) {
      atual = fila.front();
      fila.pop();
      for (Aresta *a : grafo[atual]) {
        if (level[a->to] < 0 && a->flow < a->cap) {
          level[a->to] = level[atual] + 1;
          fila.push(a->to);
        }
      }
    }
    return level[sink] != -1;
  }
  int dfs(int source, int sink, int flow) {
    if (source == sink) return flow;
    for (int &i = work[source]; i < grafo[source].size(); i++) {
      Aresta *a = grafo[source][i];
      if (a->cap <= a->flow) continue;
      int to = a->to;
      if (level[to] == level[source] + 1) {
        int delta = dfs(to, sink, min(flow, a->cap - a->flow));
        if (delta > 0) {
          a->flow += delta;
          grafo[to][a->rev]->flow -= delta;
          return delta;
        }
      }
    }
    return 0;
  }
  long long int flow(int source, int sink) {
    long long int res = 0;
    while (bfs(source, sink)) {
      for (int i = 0; i < nodes; i++) work[i] = 0;
      int delta = dfs(source, sink, INT_MAX);
      while (delta) {
        res += delta;
        delta = dfs(source, sink, INT_MAX);
      }
    }
    return res;
  }
};
int station[MAXN][MAXN], checkpoint[MAXN][MAXN], veneno[61][MAXN][MAXN];
struct coord {
  int x, y, qtd;
  coord(int a, int b, int c) {
    x = a;
    y = b;
    qtd = c;
  }
  bool is_valid(int N) {
    return (x >= 0 && x < N && y >= 0 && y < N && station[x][y] == ROOM);
  }
};
bool is_valid(int x, int y, int N) { return coord(x, y, 0).is_valid(N); }
inline bool operator==(const coord &a, const coord &b) {
  return (a.x == b.x && a.y == b.y);
}
vector<coord> pessoas, capsulas;
int moveX[] = {-1, 0, 1, 0};
int moveY[] = {0, -1, 0, 1};
int trad(char ch) {
  switch (ch) {
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      return ROOM;
    case 'Y':
      return REAC;
    case 'Z':
      return BAD_REAC;
  }
  return -1;
}
int how_much(char ch) { return ch - '0'; }
int bfs(coord from, coord to, int N) {
  bitset<MAXN> vis[MAXN];
  queue<pair<int, coord>> fila;
  fila.push({0, from});
  vis[from.x][from.y] = 1;
  while (!fila.empty()) {
    int tempo = fila.front().first;
    coord atual = fila.front().second;
    fila.pop();
    if (atual == to) return tempo;
    if (veneno[tempo][atual.x][atual.y]) {
      continue;
    }
    for (int i = 0; i < 4; i++) {
      coord next(atual.x + moveX[i], atual.y + moveY[i], 0);
      if (next.is_valid(N) && !vis[next.x][next.y]) {
        if (!veneno[tempo][next.x][next.y]) {
          fila.push({tempo + 1, next});
          vis[next.x][next.y] = 1;
        }
      }
    }
  }
  return 999;
}
void espalha_veneno(int x, int y, int T, int N) {
  veneno[0][x][y] = 1;
  for (int i = 1; i <= T; i++) {
    for (int lin = 0; lin < N; lin++) {
      for (int col = 0; col < N; col++) {
        if (veneno[i - 1][lin][col]) {
          veneno[i][lin][col] = 1;
          for (int move = 0; move < 4; move++) {
            if (is_valid(lin + moveX[move], col + moveY[move], N)) {
              veneno[i][lin + moveX[move]][col + moveY[move]] = 1;
            }
          }
        }
      }
    }
  }
}
int main() {
  int N, T;
  scanf(" %d %d", &N, &T);
  char ch;
  coord bad = {0, 0, 0};
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
      scanf(" %c", &ch);
      if (trad(ch) == ROOM && how_much(ch)) {
        pessoas.push_back(coord(i, j, how_much(ch)));
      }
      station[i][j] = trad(ch);
      if (station[i][j] == BAD_REAC) {
        bad = coord(i, j, 0);
      }
    }
  }
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
      scanf(" %c", &ch);
      if (trad(ch) == CAPS && how_much(ch)) {
        capsulas.push_back(coord(i, j, how_much(ch)));
        checkpoint[i][j] = how_much(ch);
      }
    }
  }
  Dinic *din = new Dinic(MAXN);
  int sink = MAXN - 1;
  for (size_t i = 0; i < pessoas.size(); i++) {
    din->add(0, i * 2 + 1, pessoas[i].qtd);
  }
  for (size_t i = 0; i < capsulas.size(); i++) {
    din->add(i * 2 + 2, sink, capsulas[i].qtd);
  }
  espalha_veneno(bad.x, bad.y, T, N);
  for (size_t i = 0; i < pessoas.size(); i++) {
    for (size_t j = 0; j < capsulas.size(); j++) {
      int tempo = bfs(pessoas[i], capsulas[j], N);
      if (tempo <= T) {
        din->add(i * 2 + 1, j * 2 + 2, 999);
      }
    }
  }
  printf("%d\n", din->flow(0, sink));
  delete din;
  return 0;
}
