#include <bits/stdc++.h>
using namespace std;
struct Edge {
  int from;
  int to;
  double length;
  Edge(int f, int t, double l) : from(f), to(t), length(l) {}
};
struct Node {
  vector<int> out;
};
struct Graph {
  vector<Node> nodes;
  vector<Edge> edges;
  Graph(int nr_nodes, int nr_edges) {
    nodes.resize(nr_nodes);
    edges.reserve(nr_edges);
  }
  void add_edge(int from, int to, double length) {
    Edge e = Edge(from, to, length);
    edges.push_back(e);
    nodes[from].out.push_back(edges.size() - 1);
  }
  vector<int> find_augmenting_path(int source, int sink, vector<double> flow,
                                   double *path_cap) {
    set<pair<double, int>, greater<pair<double, int> > > q;
    vector<double> capacity(nodes.size(), 0);
    vector<int> pred(nodes.size(), -1);
    vector<int> path;
    capacity[source] = INFINITY;
    q.insert(make_pair(INFINITY, source));
    while ((!q.empty()) && (capacity[sink] == 0)) {
      double cap = q.begin()->first;
      int n = q.begin()->second;
      q.erase(q.begin());
      for (unsigned int i = 0; i < nodes[n].out.size(); i++) {
        int e_idx = nodes[n].out[i];
        Edge &e = edges[e_idx];
        double e_cap = e.length - flow[e_idx];
        if ((e_cap > 0) && (min(cap, e_cap) > capacity[e.to])) {
          q.erase(make_pair(capacity[e.to], e.to));
          capacity[e.to] = min(cap, e_cap);
          q.insert(make_pair(capacity[e.to], e.to));
          pred[e.to] = e_idx;
        }
      }
    }
    *path_cap = capacity[sink];
    {
      int e_idx = pred[sink];
      while (e_idx != -1) {
        path.push_back(e_idx);
        e_idx = pred[edges[e_idx].from];
      }
    }
    return path;
  }
  double max_flow(int source, int sink) {
    Graph residual(nodes.size(), 2 * edges.size());
    vector<double> flow(2 * edges.size(), 0);
    vector<int> path;
    double path_cap;
    double max_flow = 0;
    for (unsigned int i = 0; i < edges.size(); i++) {
      residual.add_edge(edges[i].from, edges[i].to, edges[i].length);
      residual.add_edge(edges[i].to, edges[i].from, 0);
    }
    path = residual.find_augmenting_path(source, sink, flow, &path_cap);
    while (path_cap > 0) {
      for (unsigned int i = 0; i < path.size(); i++) {
        int e_idx = path[i];
        int e_ridx = e_idx + 1;
        if ((e_idx % 2) == 1) e_ridx = e_idx - 1;
        flow[e_idx] = flow[e_idx] + path_cap;
        flow[e_ridx] = flow[e_ridx] - path_cap;
      }
      path = residual.find_augmenting_path(source, sink, flow, &path_cap);
    }
    for (unsigned int i = 0; i < residual.nodes[source].out.size(); i++) {
      int e_idx = residual.nodes[source].out[i];
      max_flow = max_flow + flow[e_idx];
    }
    return max_flow;
  }
  void print_all();
};
static int n;
static int t;
struct Room {
  int i, j;
  array<bool, 61> infected;
  array<bool, 61> accessible;
  int scientists;
  int capsules;
  Room() : scientists{0}, capsules{0} {
    fill(infected.begin(), infected.end(), false);
    fill(accessible.begin(), accessible.end(), true);
  }
  int get_node_id(int timestamp) const {
    return 2 + i + n * j + (n * n) * timestamp;
  }
  void set_reactor() { fill(accessible.begin(), accessible.end(), false); }
  void set_infected(int timestamp = 0) {
    if (accessible[timestamp]) {
      accessible[timestamp] = false;
      infected[timestamp] = true;
    }
  }
  void spread_infection(int timestamp);
};
static array<array<Room, 10>, 10> floorplan;
void Room::spread_infection(int timestamp) {
  if (infected[timestamp]) {
    set_infected(timestamp + 1);
    if (i > 0) floorplan[i - 1][j].set_infected(timestamp + 1);
    if (i < (n - 1)) floorplan[i + 1][j].set_infected(timestamp + 1);
    if (j > 0) floorplan[i][j - 1].set_infected(timestamp + 1);
    if (j < (n - 1)) floorplan[i][j + 1].set_infected(timestamp + 1);
  }
}
string id_to_string(int id) {
  if (id == 0) return "source";
  if (id == 1) return "sink";
  stringstream ss;
  int row = (id - 2) % n;
  int col = ((id - 2 - row) % (n * n)) / n;
  int timestamp = (id - 2 - row - col * n) / (n * n);
  ss << "(" << row << "," << col << "," << timestamp << ")";
  return ss.str();
}
void Graph::print_all() {
  for (int i = 0; i < nodes.size(); i++) {
    Node &node = nodes[i];
    cout << id_to_string(i) << " has edges to : ";
    for (int e = 0; e < node.out.size(); ++e) {
      cout << id_to_string(edges[node.out[e]].to) << " ";
    }
    cout << endl;
  }
}
int main(void) {
  ios::sync_with_stdio(false);
  cin >> n >> t;
  for (int i = 0; i < n; i++) {
    string line;
    cin >> line;
    for (int j = 0; j < n; j++) {
      floorplan[i][j].i = i;
      floorplan[i][j].j = j;
      if (line[j] == 'Y')
        floorplan[i][j].set_reactor();
      else if (line[j] == 'Z')
        floorplan[i][j].set_infected();
      else
        floorplan[i][j].scientists = line[j] - '0';
    }
  }
  for (int i = 0; i < n; i++) {
    string line;
    cin >> line;
    for (int j = 0; j < n; j++) {
      if ((line[j] != 'Y') && (line[j] != 'Z'))
        floorplan[i][j].capsules = line[j] - '0';
    }
  }
  for (int c = 0; c <= t; c++) {
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        if (c < t) floorplan[i][j].spread_infection(c);
      }
    }
  }
  Graph g(n * n * (t + 1) + 2, 100 * 4 * 60);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      const Room &room = floorplan[i][j];
      if (room.scientists > 0)
        g.add_edge(0, room.get_node_id(0), room.scientists);
      if (room.capsules > 0) g.add_edge(room.get_node_id(t), 1, room.capsules);
      for (int c = 0; c < t; c++) {
        if (room.capsules > 0)
          g.add_edge(room.get_node_id(c), room.get_node_id(t), 1000);
        if (room.accessible[c]) {
          if (i > 0) {
            const Room &other = floorplan[i - 1][j];
            if (other.accessible[c])
              g.add_edge(room.get_node_id(c), other.get_node_id(c + 1), 1000);
          }
          if (i < (n - 1)) {
            const Room &other = floorplan[i + 1][j];
            if (other.accessible[c])
              g.add_edge(room.get_node_id(c), other.get_node_id(c + 1), 1000);
          }
          if (j > 0) {
            const Room &other = floorplan[i][j - 1];
            if (other.accessible[c])
              g.add_edge(room.get_node_id(c), other.get_node_id(c + 1), 1000);
          }
          if (j < (n - 1)) {
            const Room &other = floorplan[i][j + 1];
            if (other.accessible[c])
              g.add_edge(room.get_node_id(c), other.get_node_id(c + 1), 1000);
          }
        }
      }
    }
  }
  cout << int(g.max_flow(0, 1)) << "\n";
  return 0;
}
