#include <bits/stdc++.h>
using namespace std;
const int MAX = 300;
struct edge {
  int to;
  int nxt;
  int C;
  edge() {}
  edge(int a, int b, int c) : to(a), nxt(b), C(c) {}
};
int headg[MAX], ent;
int headr[MAX], entr;
edge edgesr[(10030 << 1) + 500], edgesg[(10030 << 1) + 500];
map<pair<int, int>, int> mm, mm2;
int s, t, n, m;
int cur[MAX], e[MAX], h[MAX];
queue<int> Q;
vector<int> negEdge;
vector<int> posEdge;
void add2(int a, int b, int c) {
  edgesr[entr].to = b, edgesr[entr].nxt = headr[a], edgesr[entr].C = c,
  headr[a] = entr++;
  if (a == s) posEdge.push_back(entr);
  if (b == s) negEdge.push_back(entr);
  edgesr[entr].to = a, edgesr[entr].nxt = headr[b], edgesr[entr].C = 0,
  headr[b] = entr++;
}
void add(int a, int b, int c) {
  edgesg[ent].to = b, edgesg[ent].C = c, edgesg[ent].nxt = headg[a],
  headg[a] = ent++;
}
void push(int u, int v, int eidx) {
  int delta = std::min(e[u], edgesr[eidx].C);
  edgesr[eidx].C -= delta;
  int rev = eidx ^ 1;
  edgesr[rev].C += delta;
  e[u] -= delta;
  e[v] += delta;
}
void relabel(int u) {
  int t = INT_MAX;
  for (int i = headr[u]; ~i; i = edgesr[i].nxt) {
    if (edgesr[i].C) {
      t = std::min(t, h[edgesr[i].to]);
    }
  }
  h[u] = t + 1;
}
void discharge(int u) {
  while (e[u] > 0) {
    int eidx = cur[u], v = edgesr[eidx].to;
    if (eidx == -1) {
      relabel(u);
      cur[u] = headr[u];
      return;
    } else if (edgesr[eidx].C && h[u] == h[v] + 1) {
      int oldE = e[v];
      push(u, v, eidx);
      if (v != t && v != s && oldE == 0) Q.push(v);
    } else
      cur[u] = edgesr[eidx].nxt;
  }
}
void iniflow() {
  for (int v = 1; v <= n; v++) e[v] = h[v] = 0;
  h[s] = n;
  for (int i = headr[s]; ~i; i = edgesr[i].nxt) {
    if (edgesr[i].C) {
      int rev = i ^ 1;
      e[edgesr[i].to] = edgesr[i].C;
      edgesr[rev].C = edgesr[i].C;
      e[s] -= edgesr[i].C;
      edgesr[i].C = 0;
    }
  }
}
int maxflow() {
  memset(headr, -1, sizeof(headr));
  negEdge.clear(), posEdge.clear();
  entr = 0;
  for (int v = 1; v <= n; v++) {
    for (int i = headg[v]; ~i; i = edgesg[i].nxt) {
      add2(v, edgesg[i].to, edgesg[i].C);
    }
  }
  iniflow();
  while (Q.size()) Q.pop();
  for (int v = 1; v <= n; v++) {
    cur[v] = headr[v];
    if (v != s && v != t && e[v] > 0) Q.push(v);
  }
  while (Q.size()) {
    int u = Q.front();
    Q.pop();
    discharge(u);
    if (e[u] > 0) Q.push(u);
  }
  int f = 0;
  for (int i = 0; i < posEdge.size(); i++) f += edgesr[posEdge[i]].C;
  for (int i = 0; i < negEdge.size(); i++) f -= edgesr[negEdge[i]].C;
  return f;
}
void printG() {
  for (int i = 1; i <= n; i++) {
    printf("v = %d -> ", i);
    for (int j = headg[i]; ~j; j = edgesg[j].nxt) {
      printf("(%lld, %lld) ", edgesg[j].to, edgesg[j].C);
    }
    printf("\n");
  }
}
int t1, n1;
const int N = 62;
char gr[N][N], gr2[N][N];
set<pair<int, int> > sp[N][N][N];
struct node {
  int type;
  int num, num2;
};
node ag[N][N];
int ex[N][N][N];
int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
set<pair<int, int> > arrive[N][N];
struct ver {
  int i, j, idx, num;
  ver(int a = 0, int b = 0, int c = 0, int d = 0)
      : i(a), j(b), idx(c), num(d) {}
};
vector<ver> st, ed;
bool inC(int i, int j) { return i >= 0 && i < n1 && j >= 0 && j < n1; }
bool kz(int i, int j) { return ag[i][j].type == 1; }
int main() {
  scanf("%d%d", &n1, &t1);
  int exi, exj;
  for (int i = 0; i < n1; i++) {
    scanf("%s", gr[i]);
    for (int j = 0; j < n1; j++) {
      if (gr[i][j] == 'Z')
        ag[i][j].type = 3, exi = i, exj = j;
      else if (gr[i][j] == 'Y')
        ag[i][j].type = 2;
      else
        ag[i][j].type = 1, ag[i][j].num = gr[i][j] - '0';
    }
  }
  for (int i = 0; i < n1; i++) {
    scanf("%s", gr2[i]);
    for (int j = 0; j < n1; j++)
      if (gr2[i][j] != 'Z' && gr2[i][j] != 'Y') ag[i][j].num2 = gr2[i][j] - '0';
  }
  memset(ex, 0, sizeof(ex));
  ex[0][exi][exj] = 1;
  for (int tt = 1; tt <= t1; tt++) {
    for (int i = 0; i < n1; i++) {
      for (int j = 0; j < n1; j++) {
        if (ex[tt - 1][i][j] == 1) {
          ex[tt][i][j] = 1;
          for (int k = 0; k < 4; k++) {
            int i1 = i + dir[k][0], j1 = j + dir[k][1];
            if (inC(i1, j1) && kz(i1, j1)) {
              ex[tt][i1][j1] = 1;
            }
          }
        }
      }
    }
  }
  for (int i = 0; i < n1; i++) {
    for (int j = 0; j < n1; j++) {
      if (ag[i][j].type == 1 && ag[i][j].num) {
        sp[i][j][0].insert({i, j});
        if (ag[i][j].num2) arrive[i][j].insert({i, j});
        for (int tt = 1; tt <= t1; tt++) {
          auto &ve = sp[i][j][tt - 1];
          for (auto &pp : ve) {
            int i1 = pp.first, j1 = pp.second;
            if (ex[tt - 1][i1][j1] == 0) {
              for (int d = 0; d < 4; d++) {
                int i2 = i1 + dir[d][0], j2 = j1 + dir[d][1];
                if (inC(i2, j2) && kz(i2, j2)) {
                  if (ex[tt - 1][i2][j2] == 0 &&
                      (ex[tt][i2][j2] == 0 || ag[i2][j2].num2)) {
                    sp[i][j][tt].insert({i2, j2});
                    if (ag[i2][j2].num2) arrive[i][j].insert({i2, j2});
                  }
                }
              }
              if (ex[tt][i1][j1] == 0 || ag[i1][j1].num2) {
                sp[i][j][tt].insert({i1, j1});
                if (ag[i1][j1].num2) arrive[i][j].insert({i1, j1});
              }
            } else
              sp[i][j][tt].insert({i1, j1});
          }
        }
      }
    }
  }
  for (int i = 0; i < n1; i++) {
    for (int j = 0; j < n1; j++) {
      if (ag[i][j].type == 1) {
        if (ag[i][j].num) st.push_back({i, j, -1, ag[i][j].num});
        if (ag[i][j].num2) ed.push_back({i, j, -1, ag[i][j].num2});
      }
    }
  }
  int ci = 2;
  for (int i = 0; i < st.size(); i++) st[i].idx = ci++;
  for (int i = 0; i < ed.size(); i++) ed[i].idx = ci++;
  s = 1, t = st.size() + ed.size() + 2;
  n = t;
  for (int i = 1; i <= n; i++) headg[i] = -1;
  ent = 0;
  for (int i = 0; i < st.size(); i++) add(1, st[i].idx, st[i].num);
  for (int i = 0; i < ed.size(); i++) add(ed[i].idx, t, ed[i].num);
  for (int i = 0; i < st.size(); i++) {
    int i1 = st[i].i, j1 = st[i].j;
    for (auto &pp : arrive[i1][j1]) {
      for (int k = 0; k < ed.size(); k++) {
        if (ed[k].i == pp.first && ed[k].j == pp.second) {
          add(st[i].idx, ed[k].idx, st[i].num);
        }
      }
    }
  }
  printf("%d\n", maxflow());
  return 0;
}
