#include <bits/stdc++.h>
using namespace std;
const long long INF = 2000000000;
int infected[14][14];
char grid[14][14];
char grid2[14][14];
int can[14][14][14][14];
int n, t;
void fillI(int i, int j, int n) {
  infected[i][j] = 1;
  int cnt = 2;
  while (true) {
    int flag = false;
    for (int x = 0; x < n; x++) {
      for (int y = 0; y < n; y++) {
        if (infected[x][y] == cnt - 1) {
          if (x > 0 && !infected[x - 1][y] && grid[x - 1][y] >= '0' &&
              grid[x - 1][y] <= '9') {
            infected[x - 1][y] = cnt;
            flag = true;
          }
          if (x < n && !infected[x + 1][y] && grid[x + 1][y] >= '0' &&
              grid[x + 1][y] <= '9') {
            infected[x + 1][y] = cnt;
            flag = true;
          }
          if (y > 0 && !infected[x][y - 1] && grid[x][y - 1] >= '0' &&
              grid[x][y - 1] <= '9') {
            infected[x][y - 1] = cnt;
            flag = true;
          }
          if (y < n && !infected[x][y + 1] && grid[x][y + 1] >= '0' &&
              grid[x][y + 1] <= '9') {
            infected[x][y + 1] = cnt;
            flag = true;
          }
        }
      }
    }
    if (!flag) break;
    cnt++;
  }
  for (int x = 0; x < n; x++)
    for (int y = 0; y < n; y++)
      if (!infected[x][y] || infected[x][y] > t + 1) infected[x][y] = t + 1;
}
queue<pair<int, int> > q;
int vis[14][14];
void bfs(int i, int j) {
  q.push(make_pair(i, j));
  vis[i][j] = 1;
  can[i][j][i][j] = 1;
  while (!q.empty()) {
    int x = q.front().first;
    int y = q.front().second;
    if ((infected[x][y] > vis[x][y])) {
      if (x > 0 && !vis[x - 1][y] && grid[x - 1][y] >= '0' &&
          grid[x - 1][y] <= '9' && infected[x - 1][y] > vis[x][y]) {
        can[i][j][x - 1][y] = 1;
        vis[x - 1][y] = vis[x][y] + 1;
        q.push(make_pair(x - 1, y));
      }
      if (x < n && !vis[x + 1][y] && grid[x + 1][y] >= '0' &&
          grid[x + 1][y] <= '9' && infected[x + 1][y] > vis[x][y]) {
        can[i][j][x + 1][y] = 1;
        vis[x + 1][y] = vis[x][y] + 1;
        q.push(make_pair(x + 1, y));
      }
      if (y > 0 && !vis[x][y - 1] && grid[x][y - 1] >= '0' &&
          grid[x][y - 1] <= '9' && infected[x][y - 1] > vis[x][y]) {
        can[i][j][x][y - 1] = 1;
        vis[x][y - 1] = vis[x][y] + 1;
        q.push(make_pair(x, y - 1));
      }
      if (y < n && !vis[x][y + 1] && grid[x][y + 1] >= '0' &&
          grid[x][y + 1] <= '9' && infected[x][y + 1] > vis[x][y]) {
        can[i][j][x][y + 1] = 1;
        vis[x][y + 1] = vis[x][y] + 1;
        q.push(make_pair(x, y + 1));
      }
    }
    q.pop();
  }
}
struct Edge {
  long long from, to, cap, flow, index;
  Edge(long long from, long long to, long long cap, long long flow,
       long long index)
      : from(from), to(to), cap(cap), flow(flow), index(index) {}
};
struct Dinic {
  long long N;
  vector<vector<Edge> > G;
  vector<Edge *> dad;
  vector<long long> Q;
  Dinic(long long N) : N(N), G(N), dad(N), Q(N) {}
  void addEdge(long long from, long long to, long long cap) {
    G[from].push_back(Edge(from, to, cap, 0, G[to].size()));
    if (from == to) G[from].back().index++;
    G[to].push_back(Edge(to, from, 0, 0, G[from].size() - 1));
  }
  long long BlockingFlow(long long s, long long t) {
    fill(dad.begin(), dad.end(), (Edge *)NULL);
    dad[s] = &G[0][0] - 1;
    long long head = 0, tail = 0;
    Q[tail++] = s;
    while (head < tail) {
      long long x = Q[head++];
      for (long long i = 0; i < G[x].size(); i++) {
        Edge &e = G[x][i];
        if (!dad[e.to] && e.cap - e.flow > 0) {
          dad[e.to] = &G[x][i];
          Q[tail++] = e.to;
        }
      }
    }
    if (!dad[t]) return 0;
    long long totflow = 0;
    for (long long i = 0; i < G[t].size(); i++) {
      Edge *start = &G[G[t][i].to][G[t][i].index];
      long long amt = INF;
      for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
        if (!e) {
          amt = 0;
          break;
        }
        amt = min(amt, e->cap - e->flow);
      }
      if (amt == 0) continue;
      for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
        e->flow += amt;
        G[e->to][e->index].flow -= amt;
      }
      totflow += amt;
    }
    return totflow;
  }
  long long GetMaxFlow(long long s, long long t) {
    long long totflow = 0;
    while (long long flow = BlockingFlow(s, t)) {
      totflow += flow;
    }
    return totflow;
  }
};
int st(int x, int y) { return (x * n) + y + 2; }
int se(int x, int y) { return 110 + (x * n) + y + 2; }
int main() {
  scanf("%d %d", &n, &t);
  int zx, zy;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      scanf(" %c", &grid[i][j]);
      if (grid[i][j] == 'Z') {
        zx = i;
        zy = j;
      }
    }
  }
  fillI(zx, zy, n);
  Dinic d = Dinic(300);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      for (int k = 0; k < n; k++) {
        for (int l = 0; l < n; l++) {
          vis[k][l] = 0;
        }
      }
      if (grid[i][j] >= '0' && grid[i][j] <= '9') {
        bfs(i, j);
      }
      if (grid[i][j] >= '1' && grid[i][j] <= '9') {
        d.addEdge(0, st(i, j), grid[i][j] - '0');
      }
      scanf(" %c", &grid2[i][j]);
      if (grid2[i][j] >= '1' && grid2[i][j] <= '9') {
        d.addEdge(se(i, j), 1, grid2[i][j] - '0');
      }
    }
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      for (int k = 0; k < n; k++) {
        for (int l = 0; l < n; l++) {
          if (grid[i][j] >= '1' && grid[i][j] <= '9' && grid2[k][l] >= '1' &&
              grid2[k][l] <= '9') {
            if (can[i][j][k][l]) {
              d.addEdge(st(i, j), se(k, l), INF);
            }
          }
        }
      }
    }
  }
  cout << d.GetMaxFlow(0, 1) << endl;
  return 0;
}
