#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>

#include <vector>
#include <queue>

using namespace std;

#define SZ(a) int((a).size())

#define REP(i,n) for(int i=0,_n=(n);i<_n;++i)
#define FOR(i,a,b) for(int i=(a),_b=(b);i<=_b;++i)

struct Pos {
   int row, col;
   Pos(int _row=0, int _col=0) : row(_row), col(_col) {}
};

int dr[] = {-1, 0, 0, 1};
int dc[] = {0, -1, 1, 0};

int N, T;
char B[12][12];
char B1[12][12];
char B2[12][12];

// time to infect all cells
int D1[12][12];
void bfs1(const Pos& src) {
   memset(D1, -1, sizeof(D1));
   D1[src.row][src.col] = 0;
   queue<Pos> q;
   q.push(src);
   while (!q.empty()) {
      Pos cur = q.front();
      q.pop();
      REP(k, 4) {
         Pos nxt(cur.row + dr[k], cur.col + dc[k]);
         if (B[nxt.row][nxt.col] != '.') continue;
         if (D1[nxt.row][nxt.col] < 0) {
            D1[nxt.row][nxt.col] = D1[cur.row][cur.col] + 1;
            q.push(nxt);
         }
      }
   }
}

int D2[12][12];
void bfs2(const Pos& src) {
   memset(D2, -1, sizeof(D2));
   D2[src.row][src.col] = 0;
   queue<Pos> q;
   q.push(src);
   while (!q.empty()) {
      Pos cur = q.front();
      q.pop();
      if (D1[cur.row][cur.col] >= 0 &&
          D2[cur.row][cur.col] >= D1[cur.row][cur.col])
         continue;
      REP(k, 4) {
         Pos nxt(cur.row + dr[k], cur.col + dc[k]);
         if (B[nxt.row][nxt.col] != '.') continue;
         if (D2[nxt.row][nxt.col] < 0) {
            if (D1[nxt.row][nxt.col] >= 0 &&
                D1[nxt.row][nxt.col] < D2[cur.row][cur.col] + 1)
               continue;
            D2[nxt.row][nxt.col] = D2[cur.row][cur.col] + 1;
            q.push(nxt);
         }
      }
   }
}

typedef vector<int> VI;
typedef vector<VI> VVI;

#define HIGHESTSETBIT(mask) ( sizeof(int)*8-1-__builtin_clz((mask)) )

#define INF 98765432

class MaxFlow {
   size_t N;
   VI bfs_par, bfs_D;
   int augmenting_path_bfs(int src, int dst, VI& path, int mincap=0);
// int augmenting_path_pfs(int src, int dst, VI& path, int mincap=0);

public:
   VVI cap;
// VVI adj;

   // OUTPUT:
   VVI flow;

   MaxFlow(int _N) : cap(_N, VI(_N)) {}
   void add_edge(int u, int v, int _cap=1);

   // Dinitz's Algoritm -- O(V^2 * E)
   int dinic(int s, int t);
};

inline void MaxFlow::add_edge(int u, int v, int _cap) {
   cap[u][v] += _cap;
}

int MaxFlow::augmenting_path_bfs(int src, int dst, VI& path, int mincap) {
   bfs_par.assign(N, -1);
   bfs_D.assign(N, -1);

   bfs_D[src] = 0;
   queue<int> q;
   q.push(src);
   while (!q.empty()) {
      int cur = q.front();
      q.pop();
      if (cur == dst) {
         int cfp = INF;
         path.resize(bfs_D[dst]+1);
         path[bfs_D[dst]] = dst;
         for (int curv = dst, k = bfs_D[dst]-1; bfs_par[curv] >= 0; --k) {
            int prev = bfs_par[curv];
            cfp = min(cfp, cap[prev][curv] - flow[prev][curv]);
            curv = path[k] = prev;
         }
         return cfp;
      }
      for (int v = 0; v < N; ++v) {
         if (bfs_D[v] < 0 && cap[cur][v] - flow[cur][v] > mincap) {
            bfs_D[v] = bfs_D[cur]+1;
            bfs_par[v] = cur;
            q.push(v);
         }
      }
   }
   path.clear();
   return 0;
}

int MaxFlow::dinic(int s, int t) {
   N = cap.size();
   flow = VVI(N, VI(N, 0));

   VI path;
   int res = 0;

   while (true) {
      // find an augmenting path
      int cfp = augmenting_path_bfs(s, t, path);
      if (path.empty())
         break;

      // try finding more paths
      for (int w = 0; w < N; ++w) {
         if (bfs_D[w] >= 0 && cap[w][t] - flow[w][t] > 0) {
            cfp = cap[w][t] - flow[w][t];
            for (int curv = w, prev = bfs_par[w]; prev >= 0;
                 curv = prev, prev = bfs_par[prev])
               cfp = min(cfp, cap[prev][curv] - flow[prev][curv]);
            flow[w][t] += cfp;
            flow[t][w] = -flow[w][t];  // -= cfp;
            for (int curv = w, prev = bfs_par[w]; prev >= 0;
                 curv = prev, prev = bfs_par[prev]) {
               flow[prev][curv] += cfp;
               flow[curv][prev] = -flow[prev][curv]; // -= cfp;
            }
            res += cfp;
         }
      }
   }
   return res;
}

int main(int argc, char* argv[]) {
   ios_base::sync_with_stdio(false);

   cin >> N >> T;
   memset(B1, '#', sizeof(B1));
   FOR(r, 1, N) {
      cin >> B1[r]+1;
      B1[r][N+1] = '#';
   }

   memset(B2, '#', sizeof(B2));
   FOR(r, 1, N) {
      cin >> B2[r]+1;
      B2[r][N+1] = '#';
   }

   memset(B, '#', sizeof(B));
   vector<Pos> scientists;
   vector<Pos> capsules;
   Pos z;
   FOR(r, 1, N) FOR(c, 1, N) {
      if (isdigit(B1[r][c])) {
         if (B1[r][c] > '0')
            scientists.push_back(Pos(r, c));
         B[r][c] = '.';
      }
      else
      if (B1[r][c] == 'Z') {
         z = Pos(r, c);
         B[r][c] = '.';
      }
      if (isdigit(B2[r][c]) && B2[r][c] > '0')
         capsules.push_back(Pos(r, c));
   }

   bfs1(z);
/*
   FOR(r, 1, N) {
      FOR(c, 1, N) {
         fprintf(stderr, "%3d ", D1[r][c]);
      }
      fprintf(stderr, "\n");
   }
*/

   const int SRC  = 0;
   const int SINK = SZ(scientists) + SZ(capsules) + 1;

   MaxFlow mf(SINK+1);
   REP(i, SZ(scientists)) {
      const Pos& s = scientists[i];
      mf.add_edge(SRC, i+1, B1[ s.row ][ s.col ] - '0');
   }

   REP(j, SZ(capsules)) {
      const Pos& c = capsules[j];
      mf.add_edge(SZ(scientists)+j+1, SINK, B2[ c.row ][ c.col ]-'0' );
   }

   REP(i, SZ(scientists)) {
      const Pos& s = scientists[i];
      bfs2(s);
/*
      fprintf(stderr, "(%d,%d)\n", s.row, s.col);
      FOR(r, 1, N) {
         FOR(c, 1, N) {
            fprintf(stderr, "%3d ", D2[r][c]);
         }
         fprintf(stderr, "\n");
      }
      fprintf(stderr, "\n");
*/
      REP(j, SZ(capsules)) {
         const Pos& c = capsules[j];
         if (D2[c.row][c.col] >= 0 && D2[c.row][c.col] <= T)
            mf.add_edge( i+1, SZ(scientists)+j+1, INF );
      }
   }

   int res = mf.dinic(SRC, SINK);
   cout << res << endl;

   return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define m_p make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
typedef long long ll;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnf(2106);
const int N = 12, INF = 1000000009;
const int xx[4] = {0, 1, 0, -1};
const int yy[4] = {1, 0, -1, 0};
struct ban
{
    int x, y;
    ban(){}
    ban(int x, int y)
    {
        this->x = x;
        this->y = y;
    }
};

int n, t;
char a[N][N], b[N][N];

int sx, sy;
int v[N][N];

void bfs(int d[N][N], int sx, int sy)
{
    bool c[N][N] = {};
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            d[i][j] = INF;
        }
    }
    queue<ban> q;
    c[sx][sy] = true;
    d[sx][sy] = 0;
    q.push(ban(sx, sy));
    while (!q.empty())
    {
        ban t = q.front();
        q.pop();
        for (int i = 0; i < 4; ++i)
        {
            ban h = t;
            h.x += xx[i];
            h.y += yy[i];
            if (h.x >= 0 && h.x < n && h.y >= 0 && h.y < n && !c[h.x][h.y] && '0' <= a[h.x][h.y] && a[h.x][h.y] <= '9')
            {
                c[h.x][h.y] = true;
                d[h.x][h.y] = d[t.x][t.y] + 1;
                q.push(h);
            }
        }
    }
}

bool dp[N * 6][N][N][N][N];
bool u[N][N][N][N];

int g[2 * N * N][2 * N * N];

int p[2 * N * N];
bool c[2 * N * N];
bool bfs1()
{
    memset(c, false, sizeof c);
    memset(p, 0, sizeof p);
    queue<int> q;
    c[0] = true;
    q.push(0);
    while (!q.empty())
    {
        int x = q.front();
        q.pop();
        if (x == 2 * n * n + 1)
            return true;
        for (int h = 0; h <= 2 * n * n + 1; ++h)
        {
            if (g[x][h])
            {
                if (!c[h])
                {
                    c[h] = true;
                    p[h] = x;
                    q.push(h);
                }
            }
        }
    }
    return false;
}

void solv()
{
    scanf("%d%d", &n, &t);
    for (int i = 0; i < n; ++i)
        scanf(" %s", a[i]);
    for (int i = 0; i < n; ++i)
        scanf(" %s", b[i]);
    scanf("%d%d", &sx, &sy);
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            if (a[i][j] == 'Z')
            {
                sx = i;
                sy = j;
            }
        }
    }
    bfs(v, sx, sy);
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            if ('0' <= a[i][j] && a[i][j] <= '9')
            {
                dp[0][i][j][i][j] = true;
            }
        }
    }
    for (int yt = 0; yt < t; ++yt)
    {
        for (int sx = 0; sx < n; ++sx)
        {
            for (int sy = 0; sy < n; ++sy)
            {
                for (int x = 0; x < n; ++x)
                {
                    for (int y = 0; y < n; ++y)
                    {
                        if (!dp[yt][sx][sy][x][y])
                            continue;
                        if (v[x][y] <= yt)
                            continue;
                        for (int i = 0; i < 4; ++i)
                        {
                            int hx = x + xx[i];
                            int hy = y + yy[i];
                            if (hx >= 0 && hx < n && hy >= 0 && hy < n && '0' <= a[hx][hy] && a[hx][hy] <= '9')
                            {
                                if (v[hx][hy] >= yt + 1)
                                    dp[yt + 1][sx][sy][hx][hy] = true;
                            }
                        }
                    }
                }
            }
        }
    }
    for (int yt = 0; yt <= t; ++yt)
    {
        for (int sx = 0; sx < n; ++sx)
        {
            for (int sy = 0; sy < n; ++sy)
            {
                for (int x = 0; x < n; ++x)
                {
                    for (int y = 0; y < n; ++y)
                    {
                        if (dp[yt][sx][sy][x][y])
                        {
                            u[sx][sy][x][y] = true;
                        }
                    }
                }
            }
        }
    }
    for (int x1 = 0; x1 < n; ++x1)
    {
        for (int y1 = 0; y1 < n; ++y1)
        {
            if ('0' <= a[x1][y1] && a[x1][y1] <= '9')
                g[0][x1 * n + y1 + 1] = a[x1][y1] - '0';
        }
    }
    for (int x2 = 0; x2 < n; ++x2)
    {
        for (int y2 = 0; y2 < n; ++y2)
        {
            if ('0' <= b[x2][y2] && b[x2][y2] <= '9')
                g[n * n + x2 * n + y2 + 1][2 * n * n + 1] = b[x2][y2] - '0';
        }
    }
    for (int x1 = 0; x1 < n; ++x1)
    {
        for (int y1 = 0; y1 < n; ++y1)
        {
            for (int x2 = 0; x2 < n; ++x2)
            {
                for (int y2 = 0; y2 < n; ++y2)
                {
                    if (!('0' <= a[x1][y1] && a[x1][y1] <= '9'))
                        continue;
                    if (!('0' <= a[x2][y2] && a[x2][y2] <= '9'))
                        continue;
                    if (!u[x1][y1][x2][y2])
                        continue;
                    g[x1 * n + y1 + 1][n * n + x2 * n + y2 + 1] = INF;
                }
            }
        }
    }
    while (bfs1())
    {
        int minu = INF;
        for (int i = 2 * n * n + 1; i; i = p[i])
        {
            minu = min(minu, g[p[i]][i]);
        }
        for (int i = 2 * n * n + 1; i; i = p[i])
        {
            g[p[i]][i] -= minu;
            g[i][p[i]] += minu;
        }
    }
    int ans = 0;
    for (int i = 0; i <= 2 * n * n + 1; ++i)
        ans += g[i][0];
    printf("%d\n", ans);
}

int main()
{
    #ifdef SOMETHING
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    #endif // SOMETHING
    solv();
    return 0;
}

//while ((double)clock() / CLOCKS_PER_SEC <= 0.9){}


#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<cstdlib>
using namespace std;
#define fre1     freopen("in.txt","r",stdin)
#define fre2     freopen("out.txt","w",stdout)
const int maxn=200;
const int maxm=100000;
const int inf=199999999;
int ma[20][20];
int mat[maxn][maxn];
int n,N,t;
string s;
int hu[maxn][3];
int re[maxn][3];
int zr,zc;
int cx,cy;
int stran[4][2]={0,-1,0,1,-1,0,1,0};

int  isok(int r,int c){
	if(r>0&&r<=n&&c>0&&c<=n&&ma[r][c]!=-1){
		return (r-1)*n+c;
	}
	return -1;
}

void BG(){
	N=n*n;
	memset(mat,-1,sizeof(mat));
	for(int r1=1;r1<=n;r1++){
		for(int c1=1;c1<=n;c1++){
			if(ma[r1][c1]==-1)continue;
			int p1=(r1-1)*n+c1;
			mat[p1][p1]=0;
			for(int i=0;i<4;i++){
				int r2=r1+stran[i][0];
				int c2=c1+stran[i][1];
				if(r2>0&&r2<=n&&c2>0&&c2<=n&&ma[r2][c2]!=-1){
					int p2=(r2-1)*n+c2;
					mat[p1][p2]=1;
				}
			}
		}
	}
}
int dis[maxn];
int qu[maxm];
int inq[maxn];
void spfa(){
	int fr=0;
	int re=1;
	for(int i=1;i<=N;i++)dis[i]=inf;
	int dd=(zr-1)*n+zc;
	dis[dd]=0;
	qu[0]=dd;
	while(fr<re){
		int now=qu[fr++];
		for(int i=1;i<=N;i++){
			if(mat[now][i]==1&&dis[i]>dis[now]+1){
				dis[i]=dis[now]+1;
				qu[re++]=i;
			}
		}
	}
}
void Floyd(){
	for(int i=1;i<=N;i++){
		for(int j=1;j<=N;j++){
			for(int z=1;z<=N;z++){
				if(mat[j][i]!=-1&&mat[i][z]!=-1){
					if(mat[j][z]==-1||mat[j][z]>mat[j][i]+mat[i][z]){
						mat[j][z]=mat[j][i]+mat[i][z];
					}
				}
			}
		}
	}
}
struct Edge{
	int st,ed,flow,next;
}edge[maxm];
int head[maxn];
int E;
int src,dest;
void addedge(int st,int ed,int flow){
	edge[E].st=st; edge[E].ed=ed; edge[E].flow=flow; edge[E].next=head[st];
	head[st]=E++;
	edge[E].st=ed; edge[E].ed=st; edge[E].flow=0;edge[E].next=head[ed];
	head[ed]=E++;
}
void BF(){
	memset(head,-1,sizeof(head));
	E=0;
	src=0;
	dest=cx+cy+1;
	for(int i=1;i<=cx;i++){
		addedge(src,i,hu[i][2]);
	}
	for(int i=1;i<=cy;i++){
		addedge(cx+i,dest,re[i][2]);
	}
	int dd=(zr-1)*n+zc;
	for(int i=1;i<=cx;i++){
		for(int j=1;j<=cy;j++){
			int p1=(hu[i][0]-1)*n+hu[i][1];
			int p2=(re[j][0]-1)*n+re[j][1];
			if(mat[p1][p2]!=-1&&mat[p1][p2]<=t&&mat[p1][p2]<dis[p2]){
				addedge(i,cx+j,inf);
			}
			else if(mat[p1][p2]!=-1&&mat[p1][p2]<=t&&mat[p1][p2]==dis[p2]){
				for(int z=0;z<4;z++){
						int rr=re[j][0]+stran[z][0];
						int cc=re[j][1]+stran[z][1];
						int pp=isok(rr,cc);
						if(pp!=-1){
							if(mat[p1][pp]==mat[p1][p2]-1&&mat[p1][pp]<dis[pp]){
								addedge(i,cx+j,inf);
							}
						}
				}
			}
		}
	}
}
int  d[maxn];
bool dinic_bfs(){
	int que[maxn];
	int front=0;
	int rear=1;
	que[0]=src;
	memset(d,-1,sizeof(d));
	d[src]=0;
	while(front<rear){
		int now=que[front++];
		for(int i=head[now];i!=-1;i=edge[i].next){
			int ed=edge[i].ed;
			if(d[ed]==-1&&edge[i].flow>0){
				d[ed]=d[now]+1;
				if(ed==dest)return d[dest]>=0;
				que[rear++]=ed;
			}
		}
	}
	return 0;
}
int stk[maxn];
int cur[maxn];
int  dinic(){
	int ret=0;
	int minf,i;
	while(dinic_bfs()){
		int u=src,tail=0;
		for( i=src;i<=dest;i++)cur[i]=head[i];//for(i=0;i<=n+1;i++)cur[i]=head[i];
		while(cur[src]!=-1){
			if(u!=dest&&cur[u]!=-1&&edge[cur[u]].flow>0&&d[u]!=-1
				&&d[u]+1==d[edge[cur[u]].ed]){
				stk[tail++]=cur[u];
				u=edge[cur[u]].ed;
			}
			else if(u==dest){
				for(minf=inf,i=tail-1;i>=0;i--){
					if(edge[stk[i]].flow<minf)minf=edge[stk[i]].flow;
				}
				for(ret+=minf,i=tail-1;i>=0;i--){
					edge[stk[i]].flow-=minf;
					edge[stk[i]^1].flow+=minf;
					if(edge[stk[i]].flow==0)tail=i;
				}
				u=edge[stk[tail]].st;
			}
			else{
				while(tail>0&&u!=src&&cur[u]==-1)u=edge[stk[--tail]].st;
				cur[u]=edge[cur[u]].next;
			}
		}
	}
	return ret;
}

int solve(){
	ma[zr][zc]=0;
	BG();
	spfa();
	ma[zr][zc]=-1;
	BG();
	Floyd();
	BF();
	int ret=dinic();
	return ret;
}

int main(){
	cin>>n>>t;
	cx=cy=0;
	memset(ma,0,sizeof(ma));
	for(int i=1;i<=n;i++){
		cin>>s;
		for(int j=0;j<n;j++){
			if(s[j]=='Y')ma[i][j+1]=-1;
			else if(s[j]=='Z'){
				zr=i; zc=j+1;
				ma[i][j+1]=-1;
			}
			else if(s[j]>'0'&&s[j]<='9'){
				hu[++cx][0]=i;
				hu[cx][1]=j+1;
				hu[cx][2]=s[j]-'0';
			}
		}
	}
	for(int i=1;i<=n;i++){
		cin>>s;
		for(int j=0;j<n;j++){
			if(s[j]>'0'&&s[j]<='9'){
				re[++cy][0]=i;
				re[cy][1]=j+1;
				re[cy][2]=s[j]-'0';
			}
		}
	}
	cout<<solve()<<endl;
	return 0;
}


#include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#include "callable.hpp/callable.hpp"
#endif
#define endl '\n'
using namespace std;
using ll = long long;
const int N = 10;
string g[N];
int n_scientists[N][N] = {};
int n_rescue[N][N] = {};
int infect_time[N][N] = {};
int di[] = {-1, 1, 0, 0};
int dj[] = {0, 0, -1, 1};
int reach_time[N][N][N][N] = {};
const int FLOW_N = 2 * N * N + 2;
const int INF = 1'000'000'000;
vector<int> adj[FLOW_N+1];
int c[FLOW_N+1][FLOW_N+1], f[FLOW_N+1][FLOW_N+1], adj_ptr[FLOW_N+1], d[FLOW_N+1], p[FLOW_N+1];
bool make_level_graph(int s, int t) {
    memset(d, -1, sizeof d);
    d[s] = 0;
    queue<int> q;
    q.push(s);
    while(not q.empty()) {
        int u = q.front();
        q.pop();
        for(int v : adj[u]) {
            if(c[u][v] - f[u][v] > 0 and d[v] == -1) {
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
    }
    return d[t] != -1;
}
bool dfs(int u, int t) {
    if(u == t) return true;
    for(int& i = adj_ptr[u]; i < adj[u].size(); i++) {
        int v = adj[u][i];
        if(d[v] == d[u] + 1 and c[u][v] - f[u][v] > 0 and dfs(v, t)) {
            p[v] = u;
            return true;
        }
    }
    return false;
}
bool find_aug_path(int s, int t) {
    memset(p, -1, sizeof p);
    p[s] = 0;
    return dfs(s, t);
}
void init_flow() {
    memset(c, 0, sizeof c);
    memset(f, 0, sizeof f);
}
void add_edge(int u, int v, int capacity) {
    adj[u].push_back(v);
    adj[v].push_back(u);
    c[u][v] += capacity;
}
int max_flow(int s, int t) {
    int max_flow_value = 0;
    while(make_level_graph(s, t)) {
        memset(adj_ptr, 0, sizeof adj_ptr);
        while(find_aug_path(s, t)) {
            int b = INF;
            for(int v = t, u = p[v]; v != s; v = u, u = p[v]) {
                b = min(b, c[u][v] - f[u][v]);
            }
            for(int v = t, u = p[v]; v != s; v = u, u = p[v]) {
                f[u][v] += b;
                f[v][u] -= b;
            }
            max_flow_value += b;
        }
    }
    return max_flow_value;
}
int node(int n, int i, int j, bool right) {
    return i * n + j + (right ? n * n : 0);
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n, t;
    cin >> n >> t;
    string line;
    pair<int, int> explode;
    for(int i = 0; i < n; i++) {
        cin >> line;
        for(int j = 0; j < n; j++) {
            if(line[j] == 'Y') {
                g[i][j] = 'Y';
            } else if(line[j] == 'Z') {
                g[i][j] = 'Z';
                explode = {i, j};
            } else {
                g[i][j] = '.';
                n_scientists[i][j] += line[j] - '0';
            }
        }
    }
    for(int i = 0; i < n; i++) {
        cin >> line;
        for(int j = 0; j < n; j++) {
            if(line[j] != 'Y' and line[j] != 'Z') {
                n_rescue[i][j] += line[j] - '0';
            }
        }
    }
    memset(infect_time, -1, sizeof infect_time);
    infect_time[explode.first][explode.second] = 0;
    queue<pair<int, int>> q;
    q.push(explode);
    while(not q.empty()) {
        int i = q.front().first, j = q.front().second;
        q.pop();
        for(int d = 0; d < 4; d++) {
            int ni = i + di[d], nj = j + dj[d];
            if(0 <= ni and ni < n and 0 <= nj and nj < n and g[ni][nj] == '.' and infect_time[ni][nj] == -1) {
                infect_time[ni][nj] = infect_time[i][j] + 1;
                q.push({ni, nj});
            }
        }
    }
    memset(reach_time, -1, sizeof reach_time);
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(g[i][j] == '.') {
                reach_time[i][j][i][j] = 0;
                queue<pair<int, int>> q;
                q.push({i, j});
                while(not q.empty()) {
                    int ii = q.front().first, jj = q.front().second;
                    q.pop();
                    if(infect_time[ii][jj] == -1 or reach_time[i][j][ii][jj] < infect_time[ii][jj]) {
                        for(int d = 0; d < 4; d++) {
                            int ni = ii + di[d], nj = jj + dj[d];
                            if(0 <= ni and ni < n and 0 <= nj and nj < n and g[ni][nj] == '.'
                            and (infect_time[ni][nj] == -1 or reach_time[i][j][ii][jj] + 1 <= infect_time[ni][nj])
                            and reach_time[i][j][ni][nj] == -1) {
                                reach_time[i][j][ni][nj] = reach_time[i][j][ii][jj] + 1;
                                q.push({ni, nj});
                            }
                        }
                    }
                }
            }
        }
    }
    int src = 2 * n * n, sink = 2 * n * n + 1;
    init_flow();
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(n_scientists[i][j]) {
                add_edge(src, node(n, i, j, false), n_scientists[i][j]);
            }
            if(n_rescue[i][j]) {
                add_edge(node(n, i, j, true), sink, n_rescue[i][j]);
            }
            for(int ii = 0; ii < n; ii++) {
                for(int jj = 0; jj < n; jj++) {
                    if(0 <= reach_time[i][j][ii][jj] and reach_time[i][j][ii][jj] <= t) {
                        add_edge(node(n, i, j, false), node(n, ii, jj, true), INF);
                    }
                }
            }
        }
    }
    cout << max_flow(src, sink) << endl;
    return 0;
}


#include <iostream>
#include <queue>
using namespace std;
char a[20][20],b[20][20];
queue <pair <int,int> > q;
int Dis[20][20],dis[11][11][11][11];
int fx[5]={-1,1,0,0},fy[5]={0,0,-1,1};
struct edge
{
	int u,v,fl,c,n;
}e[200005];
int cnt,head[505],p[505],v[505],s=501,t=502,ans,n,m,dep[505];
inline void add(int u,int v,int w)
{
//	cout << u << " " << v << " " << w << "\n";
	e[++cnt]={u,v,0,w,head[u]};
	head[u]=cnt;
	e[++cnt]={v,u,0,0,head[v]};
	head[v]=cnt;
}
inline bool Find()
{
	queue <int> q;
	for(int i=0;i<=t;i++)
		v[i]=dep[i]=0;
	q.push(s);
	v[s]=1;
	dep[s]=1;
	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		for(int i=head[x];i;i=e[i].n)
		{
			if(!v[e[i].v]&&e[i].fl<e[i].c)
			{
				p[e[i].v]=i;
				q.push(e[i].v);
				v[e[i].v]=1;
				dep[e[i].v]=dep[x]+1;
				if(e[i].v==t)
					return 1;
			}
		}
	}
	return 0;
}
inline int dfs(int x,int now)
{
	if(x==t||!now)
		return now;
	int t=now;
	for(int i=head[x];i;i=e[i].n)
	{
		if(e[i].c>e[i].fl&&dep[e[i].v]==dep[x]+1)
		{
            int delta=dfs(e[i].v,min(t,e[i].c-e[i].fl));
			if(!delta)
				dep[e[i].v]=0;
            e[i].fl+=delta;
            e[((i-1)^1)+1].fl-=delta;
            t-=delta;
            if(t==0)
				break;
        }
	}
	return now-t;
}
inline void dinic()
{
	while(Find())
		ans+=dfs(s,1000000007);
}
int main(int argc, char** argv) {
	int n,t;
	cin >> n >> t;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			Dis[i][j]=10000;
			cin >> a[i][j];
			if(a[i][j]=='Z')
				q.push({i,j}),Dis[i][j]=0;
			if(a[i][j]<='9') add(s,(i-1)*n+j,a[i][j]-'0');
		}
	}
	while(!q.empty())
	{
		int x=q.front().first,y=q.front().second;
		q.pop();
		for(int i=0;i<4;i++)
		{
			int nx=x+fx[i],ny=y+fy[i];
			if(nx>0&&ny>0&&nx<=n&&ny<=n&&a[nx][ny]<='9'&&Dis[nx][ny]>Dis[x][y]+1)
				Dis[nx][ny]=Dis[x][y]+1,q.push({nx,ny});
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i][j]>'9') continue;
			for(int k=1;k<=n;k++)
				for(int l=1;l<=n;l++)
					dis[i][j][k][l]=10000;
			q.push({i,j});
			dis[i][j][i][j]=0;
			while(!q.empty())
			{
				int x=q.front().first,y=q.front().second;
				q.pop();
				for(int f=0;f<4;f++)
				{
					int nx=x+fx[f],ny=y+fy[f];
					if(nx>0&&ny>0&&nx<=n&&ny<=n&&a[nx][ny]<='9'&&dis[i][j][nx][ny]>dis[i][j][x][y]+1&&dis[i][j][x][y]<Dis[x][y])
					{
						dis[i][j][nx][ny]=dis[i][j][x][y]+1;
							q.push({nx,ny});
					}
				}
			}
			for(int k=1;k<=n;k++)
				for(int l=1;l<=n;l++)
					if(dis[i][j][k][l]<=min(Dis[k][l],t))
						add((i-1)*n+j,(k-1)*n+l+100,10000);
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin >> b[i][j];
			if(b[i][j]<='9') add((i-1)*n+j+100,502,b[i][j]-'0');
		}
	}
	dinic();
	cout << ans;
	return 0;
}


#define _USE_MATH_DEFINES

#include <cmath>
#include <cstdio>

#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define mp make_pair
#define pb push_back

#define DEBUG(x) cout << #x << ": " << (x) << endl;

char A[12][12];
char B[12][12];
    int n, t;
bool _dp[70][12][12][12][12];
bool dp[12][12][12][12];

int tim[12][12];

void setdp(int tt, int x, int y, int x0, int y0) {
    if (t >= 70) return;
    if (x < 0 || x >= n || y < 0 || y >= n)
        return;
    if (A[x][y] < '0' || A[x][y] > '9')
        return;
    if (tt > t+1)
        return;
    if (_dp[tt][x][y][x0][y0])
        return;
    if (tt > tim[x][y] && tim[x][y] != 0)
        return;
    if (tt == tim[x][y] && tim[x][y] != 0 && (B[x][y] > '9' || B[x][y] <= '0'))
        return;
    _dp[tt][x][y][x0][y0] = true;

    if (tt < tim[x][y])
    {
    setdp(tt+1, x, y, x0, y0);
    setdp(tt+1, x+1, y, x0, y0);
    setdp(tt+1, x-1, y, x0, y0);
    setdp(tt+1, x, y+1, x0, y0);
    setdp(tt+1, x, y-1, x0, y0);
    }
}

vector<vector<int> > G;
int F[210][210];
int E[210], H[210];
int C[210][210];

int pN[11][11];

int main() {
#ifndef ONLINE_JUDGE
    freopen( "1.txt", "rt", stdin );
    //freopen("output.txt", "wt", stdout);
#endif

    cin >> n >> t;

    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> A[i][j];

    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> B[i][j];

    deque<pair<int,int> > q;

    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            tim[i][j] = -1;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            if (A[i][j] == 'Z')
            {
                tim[i][j] = 0;
                q.push_back(mp(i,j));
            }

    int di[] = {-1, 0, 1, 0};
    int dj[] = {0, -1, 0, 1};

    while (!q.empty())
    {
        pair<int,int> p = q.front();
        q.pop_front();
        if (tim[p.first][p.second] >= t)
            continue;
        for (int d = 0; d <= 3; d++)
        {
            pair<int,int> np = mp(p.first+di[d], p.second+dj[d]);
            if (np.first >= 0 && np.first < n && np.second >= 0 && np.second < n &&
                A[np.first][np.second] >= '0' && A[np.first][np.second] <= '9' && tim[np.first][np.second]==-1)
            {
                tim[np.first][np.second] = tim[p.first][p.second]+1;
                q.push_back(np);
            }
        }
    }
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            if (tim[i][j] == -1)
                tim[i][j] = t;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            if (A[i][j] >= '0' && A[i][j] <= '9')
                setdp(0,i,j,i,j);

    vector<int> st;
    G.pb(st);

    for (int i1 = 0; i1 < n; i1++)
        for (int j1 = 0; j1 < n; j1++)
            for (int i2 = 0; i2 < n; i2++)
                for (int j2 = 0; j2 < n; j2++)
                    for (int nt = 0; nt <= t; nt++)
                        dp[i1][j1][i2][j2] |= _dp[nt][i1][j1][i2][j2];

    for (int i1 = 0; i1 < n; i1++)
        for (int j1 = 0; j1 < n; j1++)
            if (A[i1][j1] > '0' && A[i1][j1] <= '9')
            {
                int k = G.size();
                vector<int> g;
                G.push_back(g);
                E[k] = A[i1][j1] - '0';

                for (int i2 = 0; i2 < n; i2++)
                    for (int j2 = 0; j2 < n; j2++)
                        if (B[i2][j2] > '0' && B[i2][j2] <= '9')
                        if (dp[i2][j2][i1][j1])
                        {
                            int _k;

                            if (pN[i2][j2] == 0)
                            {
                                vector<int> _g;
                                _k = G.size();
                                G.push_back(_g);
                                pN[i2][j2] = _k;
                            }
                            else
                            {
                                _k = pN[i2][j2];
                            }

                            G[k].pb(_k);
                            G[_k].pb(k);
                            C[k][_k] = 10000;
                            C[_k][k] = 0;
                        }
            }

    for (int i2 = 0; i2 < n; i2++)
        for (int j2 = 0; j2 < n; j2++)
            if (B[i2][j2] > '0' && B[i2][j2] <= '9' && pN[i2][j2] > 0)
            {
                int _k;
                _k = pN[i2][j2];
                G[_k].push_back(0);

                C[_k][0] = B[i2][j2] - '0';
                C[0][_k] = 0;
            }

    while(1)
    {
        bool ff = true;
        for (int i = 1; i < G.size(); i++)
            while (E[i] > 0)
            {
                bool f = true;
                int minH = 10000;
                for (int _j = 0; _j < G[i].size(); _j++)
                {
                    int j = G[i][_j];
                    if (C[i][j] - F[i][j]) minH = min(minH, H[j]);
                    if (C[i][j] - F[i][j] > 0 && H[i]==H[j]+1)
                    {
                        int d = min(C[i][j] - F[i][j], E[i]);
                        F[i][j] += d;
                        F[j][i] -= d;
                        E[i] -= d;
                        E[j] += d;
                        f = false;
                        ff = false;
                        if (E[i] == 0)
                            goto next;

                    }
                }
                if (H[i] != minH+1 && minH != 10000)
                    f = false,
                    ff = false,
                    H[i] = minH+1;

                if (f)
next:                break;
            }
        if (ff)
            break;
    }

exit:
    cout << E[0];
    return ( 0 );
}


#include<bits/stdc++.h>
using namespace std;

#define LL long long int
#define ULL unsigned LL
#define PII pair<int,int>
#define PB push_back
#define MP make_pair
#define INF 1000000000
#define MOD 1000000007

int shortest[15][15][15][15];
int cap[400][400];
char scien[20][20];
char reac[20][20];
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
int iter = 3;
int vis[400];

int n, t;
int aug(int cnode, int dest, int bneck) {
    if (cnode == dest) {
        return bneck;
    }
    if (vis[cnode] == iter) {
        return 0;
    }
    vis[cnode] = iter;
    for (int i = 0; i <= dest; i++) {
        int cret = 0;
        if (cap[cnode][i] > 0 && (cret = aug(i, dest, min(bneck, cap[cnode][i])))) {
            // cout << cnode << " ";
            cap[cnode][i] -= cret;
            cap[i][cnode] += cret;
            return cret;
        }
    }
    return 0;
}
int getnode(int x, int y) {
    return (x - 1) * n + y - 1;
}
int reach[13][13];
int treach[13][13];
void expand(int val) {
    int i, j, k;
    for (i = 1; i <= n; i++)
        for (j = 1; j <=n; j++)
            treach[i][j] = reach[i][j];
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            if (treach[i][j] == val) {
                for (k = 0; k < 4; k++) {
                    int ni = i + dx[k];
                    int nj = j + dy[k];
                    if (ni > 0 && nj > 0 && ni <= n && nj <= n && treach[ni][nj] < val && scien[ni][nj] != 'Y') {
                        reach[ni][nj] = val;
                    }
                }
            }
        }
    }
}
bool canreach(int sx, int sy, int tx, int ty, int ix, int iy) {
    memset(reach, 0, sizeof(reach));
    reach[sx][sy] = 1;
    reach[ix][iy] = 2;
    int iters = 100;
    while (iters--) {
        expand(1);
        if (reach[tx][ty] == 1)
            return true;
        expand(2);
        if (reach[tx][ty] == 2)
            return false;
    }
    return false;
}
int main() {
    int infx, infy;
    memset(shortest, 1, sizeof(shortest));
    cin >> n >> t;
    int i, j;
    for (i = 1; i <= n; i++) {
        scanf(" %s", scien[i] + 1);
        for (j = 1; j <= n; j++) {
            shortest[i][j][i][j] = 0;
            if (scien[i][j] == 'Z') {
                infx = i;
                infy = j;
            }
        }
    }
    for (i = 1; i <= n; i++) {
        scanf(" %s", reac[i] + 1);
    }
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            for (int k = 0; k < 4; k++) {
                int ni = i + dx[k];
                int nj = j + dy[k];
                if (ni <= n && ni > 0 && nj <= n && nj > 0) {
                    if (scien[i][j] != 'Y' && scien[ni][nj] != 'Y')
                        shortest[i][j][ni][nj] = 1;
                }
            }
        }
    }
    int ki, kj, ii, ij, ji, jj;
    for (ki = 1; ki <= n; ki++) {
        for (kj = 1; kj <= n; kj++) {
            for (ii = 1; ii <= n; ii++) {
                for (ij = 1; ij <= n; ij++) {
                    for (ji = 1; ji <= n; ji++) {
                        for (jj = 1; jj <= n; jj++) {
                            shortest[ii][ij][ji][jj] = min(
                                    shortest[ii][ij][ji][jj],
                                    shortest[ii][ij][ki][kj] + shortest[ki][kj][ji][jj]
                                    );
                        }
                    }
                }
            }
        }
    }
    int src = n * n * 2 + 1;
    int dest = n * n * 2 + 2;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            if (isdigit(scien[i][j])) {
                cap[src][getnode(i, j)] = scien[i][j] - '0';
            }
            if (isdigit(reac[i][j])) {
                cap[n * n + getnode(i, j)][dest] = reac[i][j] - '0';
            }

            if (isdigit(scien[i][j])) {
                for (ki = 1; ki <= n; ki++) {
                    for (kj = 1; kj <= n; kj++) {
                        if (scien[i][j] > '0' && reac[ki][kj] > '0') {
                            if (isdigit(reac[ki][kj]) && shortest[i][j][ki][kj] <= t && canreach(i, j, ki, kj, infx, infy)) {
                                // printf("(%d, %d) can reach (%d, %d)\n", i, j, ki, kj);
                                cap[getnode(i, j)][n * n + getnode(ki, kj)] = 1000;
                            }
                        }
                    }
                }
            }
        }
    }
    int mflow = 0, ret;
    while ((ret = aug(src, dest, 1000))) {
        // cout << endl;
        mflow += ret;
        iter ++;
    }
    cout << mflow << endl;
    return 0;
}


#include <cstdio>
#include <cstring>
#include <queue>
#include <cctype>
#define MAXN 256
#define MAXT 64
#define MAXE MAXN * MAXN
#define INF 1000000000
using namespace std;
class Dinic {
	struct edge {
		int u, v, f, c, nx;
		edge() {}
		edge(int u, int v, int f, int c, int nx): u(u), v(v), f(f), c(c), nx(nx) {}
	} e[MAXE];
	int n, m, src, dst, head[MAXN], work[MAXN], d[MAXN];
	bool _bfs() {
		static int q[MAXN], le, ri;
		le = ri = 0;
		memset(d, -1, sizeof(int) * n);
		q[ri++] = src;
		d[src] = 0;
		while(le < ri) {
			for(int k = q[le++], i = head[k]; i != -1; i = e[i].nx) {
				if(e[i].f < e[i].c && d[e[i].v] == -1) {
					d[e[i].v] = d[k] + 1;
					q[ri++] = e[i].v;
				}
			}
		}
		return (d[dst] != -1);
	}
	int _dfs(int u, int f) {
		if(u == dst)
			return f;
		int minf;
		for(int& i = work[u]; i != -1; i = e[i].nx) {
			if(e[i].f < e[i].c && d[e[i].v] == d[u] + 1) {
				minf = _dfs(e[i].v, min(f, e[i].c - e[i].f));
				if(minf > 0) {
					e[i].f += minf;
					e[i ^ 1].f -= minf;
					return minf;
				}
			}
		}
		return 0;
	}
public:
	void init(int n, int src, int dst) {
		this->n = n;
		this->src = src;
		this->dst = dst;
		m = 0;
		memset(head, -1, sizeof(int) * n);
	}
	void addEdge(int u, int v, int c) {
		//printf("%d %d %d\n", u, v, c);
		e[m] = edge(u, v, 0, c, head[u]);
		head[u] = m++;
		e[m] = edge(v, u, 0, 0, head[v]);
		head[v] = m++;
	}
	int maxFlow() {
		int ret = 0, delta;
		while(_bfs()) {
			memcpy(work, head, sizeof(int) * n);
			while(true) {
				delta = _dfs(src, INF);
				if(delta == 0)
					break;
				ret += delta;
			}
		}
		return ret;
	}
} dinic;
#define MAX 12
int n, t, zx, zy;
char smp[MAX][MAX], cmp[MAX][MAX], work[MAX][MAX];
int vis[MAX][MAX];
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, -1, 0, 1};
inline int X(int i, int j) { return i * n + j; }
inline int Y(int i, int j) { return n * n + i * n + j; }
inline int S() { return n * n * 2; }
inline int T() { return S() + 1; }
inline int N() { return T() + 1; }
struct qNode {
	int x, y, t, type;
	qNode() {}
	qNode(int x, int y, int t, int type): x(x), y(y), t(t), type(type) {}
};
void bfs(int sx, int sy) {
	queue<qNode> q;
	q.push(qNode(sx, sy, 0, 0));
	vis[sx][sy] = 1;
	q.push(qNode(zx, zy, 0, 1));
	while(!q.empty()) {
		qNode u = q.front();
		int nx, ny;
		q.pop();
		if(u.t == t)
			break;
		if(u.type == 0 && isalpha(work[u.x][u.y]))
			continue;
		for(int i = 0; i < 4; ++i) {
			nx = u.x + dx[i];
			ny = u.y + dy[i];
			if(nx >= 0 && nx < n && ny >= 0 && ny < n) {
				if(u.type == 0 && !vis[nx][ny] && !isalpha(work[nx][ny])) {
					vis[nx][ny] = 1;
					q.push(qNode(nx, ny, u.t + 1, 0));
				}
				else if(u.type == 1 && !isalpha(work[nx][ny])) {
					work[nx][ny] = 'Z';
					q.push(qNode(nx, ny, u.t + 1, 1));
				}
			}
		}
	}
}
int main() {
	while(scanf("%d%d", &n, &t) != EOF) {
		dinic.init(N(), S(), T());
		for(int i = 0; i < n; ++i) {
			scanf("%s", smp[i]);
			for(int j = 0; j < n; ++j)
				if(isdigit(smp[i][j]) && smp[i][j] > '0')
					dinic.addEdge(S(), X(i, j), smp[i][j] - '0');
				else if(smp[i][j] == 'Z') {
					zx = i;
					zy = j;
				}
		}
		for(int i = 0; i < n; ++i) {
			scanf("%s", cmp[i]);
			for(int j = 0; j < n; ++j)
				if(isdigit(cmp[i][j]) && cmp[i][j] > '0')
					dinic.addEdge(Y(i, j), T(), cmp[i][j] - '0');
		}
		for(int i = 0; i < n; ++i)
			for(int j = 0; j < n; ++j) {
				if(!isdigit(smp[i][j]) || smp[i][j] <= '0')
					continue;
				memset(vis, 0, sizeof(vis));
				memcpy(work, smp, sizeof(smp));
				bfs(i, j);
				for(int xi = 0; xi < n; ++xi)
					for(int yi = 0; yi < n; ++yi) {
						if(!isdigit(cmp[xi][yi]) || cmp[xi][yi] <= '0')
							continue;
						if(vis[xi][yi]) {
							dinic.addEdge(X(i, j), Y(xi, yi), INF);
						}
					}
			}
		printf("%d\n", dinic.maxFlow());
	}
	return 0;
}


#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;

typedef long long LL;

const int inf=0x3f3f3f3f;

const int N=210;

struct Edge
{
	int to,w,next;
}edge[N*N];//边数

const int b[4][2]={0,1,0,-1,1,0,-1,0};

int n,t,st=N-1,ed=st-1,cap[15][15],sci[15][15],maze[65][15][15],head[N],cnt;

bool vis[15][15],dp[65][15][15][15][15];

void addedge(int u,int v,int w)
{
	edge[cnt].to=v;
	edge[cnt].w=w;
	edge[cnt].next=head[u];
	head[u]=cnt++;
	edge[cnt].to=u;
	edge[cnt].w=0;//反向边边权设置为0
	edge[cnt].next=head[v];
	head[v]=cnt++;
}

int d[N],now[N];//深度 当前弧优化

bool bfs(int s,int t)//寻找增广路
{
	memset(d,0,sizeof(d));
	queue<int>q;
	q.push(s);
	now[s]=head[s];
	d[s]=1;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=head[u];i!=-1;i=edge[i].next)
		{
			int v=edge[i].to;
			int w=edge[i].w;
			if(d[v])
				continue;
			if(!w)
				continue;
			d[v]=d[u]+1;
			now[v]=head[v];
			q.push(v);
			if(v==t)
				return true;
		}
	}
	return false;
}

int dinic(int x,int t,int flow)//更新答案
{
	if(x==t)
		return flow;
	int rest=flow,i;
	for(i=now[x];i!=-1&&rest;i=edge[i].next)
	{
		int v=edge[i].to;
		int w=edge[i].w;
		if(w&&d[v]==d[x]+1)
		{
			int k=dinic(v,t,min(rest,w));
			if(!k)
				d[v]=0;
			edge[i].w-=k;
			edge[i^1].w+=k;
			rest-=k;
		}
	}
	now[x]=i;
	return flow-rest;
}

int solve(int st,int ed)
{
	int ans=0,flow;
	while(bfs(st,ed))
		while(flow=dinic(st,ed,inf))
			ans+=flow;
	return ans;
}

int get_id(int x,int y,int k)//science:0 capsule:1
{
	return (x-1)*n+y+k*n*n;
}

void dfs(int x,int y,int xx,int yy,int step)
{
	vis[xx][yy]=true;
	dp[step][x][y][xx][yy]=true;
	if(step>=t||maze[step][xx][yy])
		return;
	for(int k=0;k<4;k++)
	{
		int nx=xx+b[k][0];
		int ny=yy+b[k][1];
		if(nx<=0||ny<=0||nx>n||ny>n)
			continue;
		if(vis[nx][ny])
			continue;
		if(maze[step][nx][ny])
			continue;
		dfs(x,y,nx,ny,step+1);
	}
}

void init()
{
	memset(now,0,sizeof(now));
	memset(head,-1,sizeof(head));
	cnt=0;
	for(int time=1;time<=t;time++)
	{
		for(int x=1;x<=n;x++)
		{
			for(int y=1;y<=n;y++)
			{
				if(maze[time-1][x][y])
					maze[time][x][y]=maze[time-1][x][y];
				else
				{
					for(int k=0;k<4;k++)
					{
						int xx=x+b[k][0];
						int yy=y+b[k][1];
						if(xx<=0||yy<=0||xx>n||yy>n)
							continue;
						if(maze[time-1][xx][yy]==2)
							maze[time][x][y]=2;
					}
				}
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(sci[i][j])
			{
				memset(vis,false,sizeof(vis));
				dfs(i,j,i,j,0);
			}
		}
	}
	for(int i=1;i<=t;i++)
		for(int x=1;x<=n;x++)
			for(int y=1;y<=n;y++)
				for(int xx=1;xx<=n;xx++)
					for(int yy=1;yy<=n;yy++)
				dp[i][x][y][xx][yy]|=dp[i-1][x][y][xx][yy];
}

int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);
	scanf("%d%d",&n,&t);
    for(int i=1;i<=n;i++)
    {
    	char s[15];
    	scanf("%s",s+1);
    	for(int j=1;j<=n;j++)
    	{
    		if(isdigit(s[j]))
    			sci[i][j]=s[j]-'0';
    		else if(s[j]=='Y')
    			maze[0][i][j]=1;
    		else if(s[j]=='Z')
    			maze[0][i][j]=2;
		}
	}
	for(int i=1;i<=n;i++)
	{
		char s[15];
		scanf("%s",s+1);
		for(int j=1;j<=n;j++)
		{
			if(isdigit(s[j]))
				cap[i][j]=s[j]-'0';
		}
	}
	init();
    for(int i=1;i<=n;i++)
    {
    	for(int j=1;j<=n;j++)
    	{
    		if(sci[i][j])
    			addedge(st,get_id(i,j,0),sci[i][j]);
    		if(cap[i][j])
    			addedge(get_id(i,j,1),ed,cap[i][j]);
		}
	}
	for(int x=1;x<=n;x++)
		for(int y=1;y<=n;y++)
			for(int xx=1;xx<=n;xx++)
				for(int yy=1;yy<=n;yy++)
					if(sci[x][y]&&cap[xx][yy]&&dp[t][x][y][xx][yy])
						addedge(get_id(x,y,0),get_id(xx,yy,1),inf);
	printf("%d\n",solve(st,ed));

    return 0;
}
    			   			 	  		 						 				//hellobig_tq


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
#define y1 Y1
const int INF=1<<29;
const int MAXN=500;
struct edge
{
    int a,b,cap,flow;
};
bool m[11][11];
vector <int> g[MAXN];
vector <edge> e;
int d[MAXN],ptr[MAXN],n,xb,yb,t,temp[11][11],kaps[11][11];
int way(int x1,int y1,int x2,int y2)
{
    queue <pair <int,pair <int,int> > > l;
    l.push(make_pair(0,make_pair(x1,y1)));
    int h[11][11];
    for(int p=0;p<n;p++)
        for(int b=0;b<n;b++)
            h[p][b]=INF;
    while (!l.empty())
    {
        int v=l.front().first,x=l.front().second.first,y=l.front().second.second;
        l.pop();
        h[x][y]=v;
        if (x>0 && m[x-1][y] && h[x-1][y]>h[x][y]+1 && (x-1==x2 && y==y2 && temp[x-1][y]>=h[x][y]+1 || !(x-1==x2 && y==y2) && temp[x-1][y]>h[x][y]+1)) l.push(make_pair(v+1,make_pair(x-1,y)));
        if (y>0 && m[x][y-1] && h[x][y-1]>h[x][y]+1 && (x==x2 && y-1==y2 && temp[x][y-1]>=h[x][y]+1 || !(x==x2 && y-1==y2) && temp[x][y-1]>h[x][y]+1)) l.push(make_pair(v+1,make_pair(x,y-1)));
        if (x<n-1 && m[x+1][y] && h[x+1][y]>h[x][y]+1 && (x+1==x2 && y==y2 && temp[x+1][y]>=h[x][y]+1 || !(x+1==x2 && y==y2) && temp[x+1][y]>h[x][y]+1)) l.push(make_pair(v+1,make_pair(x+1,y)));
        if (y<n-1 && m[x][y+1] && h[x][y+1]>h[x][y]+1 && (x==x2 && y+1==y2 && temp[x][y+1]>=h[x][y]+1 || !(x==x2 && y+1==y2) && temp[x][y+1]>h[x][y]+1)) l.push(make_pair(v+1,make_pair(x,y+1)));
    }
    return h[x2][y2];
}
void add_edge(int a,int b,int cap)
{
    edge e1={a,b,cap,0};
    edge e2={b,a,0,0};
    g[a].push_back((int)e.size());
    e.push_back(e1);
    g[b].push_back((int)e.size());
    e.push_back(e2);
}
bool bfs()
{
    queue <int> q;
    q.push(0);
    memset(d,-1,(n*n*2+2)*sizeof d[0]);
    d[0]=0;
    while (!q.empty() && d[n*n*2+1]==-1)
    {
        int v=q.front();
        q.pop();
        for(size_t j=0;j<g[v].size();j++)
        {
            int id=g[v][j],to=e[id].b;
            if (d[to]==-1 && e[id].flow<e[id].cap)
            {
                q.push(to);
                d[to]=d[v]+1;
            }
        }
    }
    return d[n*n*2+1]!=-1;
}
int dfs(int v,int flow)
{
    if (!flow) return 0;
    if (v==n*n*2+1) return flow;
    for(;ptr[v]<(int)g[v].size();ptr[v]++)
    {
        int id=g[v][ptr[v]],to=e[id].b;
        if (d[to]!=d[v]+1) continue;
        int pushed=dfs(to,min(flow,e[id].cap-e[id].flow));
        if (pushed)
        {
            e[id].flow+=pushed;
            e[id^1].flow-=pushed;
            return pushed;
        }
    }
    return 0;
}
int max_flow()
{
    int flow=0;
    for(;;)
    {
        if (!bfs()) break;
        memset(ptr,0,(n*n*2+2)*sizeof ptr[0]);
        while (int pushed=dfs(0,INF))
            flow+=pushed;
    }
    return flow;
}
int main()
{
    cin>>n>>t;
    queue <pair <int,pair <int,int> > > l;
    char x;
    int k=1;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cin>>x;
            temp[i][j]=t;
            if (x=='Z')
            {
                xb=i;
                yb=j;
                m[i][j]=false;
            } else
            if (x=='Y') m[i][j]=false; else m[i][j]=true;
            add_edge(0,k++,x=='Z' || x=='Y'?0:x-48);
        }
    }
    k=n*n+1;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            cin>>x;
            if (x>='0' && x<='9') kaps[i][j]=x-48;
            add_edge(k++,n*n*2+1,x=='Z' || x=='Y'?0:x-48);
        }
    l.push(make_pair(0,make_pair(xb,yb)));
    while (!l.empty())
    {
        int v=l.front().first,x=l.front().second.first,y=l.front().second.second;
        l.pop();
        temp[x][y]=v;
        if (x>0 && v+1<temp[x-1][y] && m[x-1][y]) l.push(make_pair(v+1,make_pair(x-1,y)));
        if (y>0 && v+1<temp[x][y-1] && m[x][y-1]) l.push(make_pair(v+1,make_pair(x,y-1)));
        if (x<n-1 && v+1<temp[x+1][y] && m[x+1][y]) l.push(make_pair(v+1,make_pair(x+1,y)));
        if (y<n-1 && v+1<temp[x][y+1] && m[x][y+1]) l.push(make_pair(v+1,make_pair(x,y+1)));
    }
    /*for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
            cout<<temp[i][j]<<" ";
        cout<<endl;
    }*/
    k=0;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            int k1=n*n;
            k++;
            for(int z=0;z<n;z++)
                for(int w=0;w<n;w++)
                {
                    k1++;
                    if (m[i][j] && m[z][w] && way(i,j,z,w)<=t) add_edge(k,k1,INF);
                }
        }
    /*for(int i=0;i<n*n*2+1;i++)
        for(size_t j=0;j<g[i].size();j++)
            if (e[g[i][j]].cap>0) cout<<i<<" "<<e[g[i][j]].b<<" "<<e[g[i][j]].cap<<endl;*/
    cout<<max_flow();
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
char s1[15][15], s2[15][15];
int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int idx[65][15][15];
int dp[15][15];
int id = 1;

typedef long long LL;
struct Edge {
  int u, v;
  LL cap, flow;
  Edge() {}
  Edge(int u, int v, LL cap): u(u), v(v), cap(cap), flow(0) {}
};

struct Dinic {
  int N;
  vector<Edge> E;
  vector<vector<int>> g;
  vector<int> d, pt;

  Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}

  void AddEdge(int u, int v, LL cap) {
    if (u != v) {
      E.emplace_back(Edge(u, v, cap));
      g[u].emplace_back(E.size() - 1);
      E.emplace_back(Edge(v, u, 0));
      g[v].emplace_back(E.size() - 1);
    }
  }

  bool BFS(int S, int T) {
    queue<int> q({S});
    fill(d.begin(), d.end(), N + 1);
    d[S] = 0;
    while(!q.empty()) {
      int u = q.front(); q.pop();
      if (u == T) break;
      for (int k: g[u]) {
        Edge &e = E[k];
        if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
          d[e.v] = d[e.u] + 1;
          q.emplace(e.v);
        }
      }
    }
    return d[T] != N + 1;
  }

  LL DFS(int u, int T, LL flow = -1) {
    if (u == T || flow == 0) return flow;
    for (int &i = pt[u]; i < g[u].size(); ++i) {
      Edge &e = E[g[u][i]];
      Edge &oe = E[g[u][i]^1];
      if (d[e.v] == d[e.u] + 1) {
        LL amt = e.cap - e.flow;
        if (flow != -1 && amt > flow) amt = flow;
        if (LL pushed = DFS(e.v, T, amt)) {
          e.flow += pushed;
          oe.flow -= pushed;
          return pushed;
        }
      }
    }
    return 0;
  }

  LL MaxFlow(int S, int T) {
    LL total = 0;
    while (BFS(S, T)) {
      fill(pt.begin(), pt.end(), 0);
      while (LL flow = DFS(S, T))
        total += flow;
    }
    return total;
  }
};

int main(){
	memset(dp, -1, sizeof(dp));
	int n, t;
	scanf("%d%d", &n, &t);
	for(int i=1;i<=n;i++){
		scanf("%s", s1[i]+1);
	}
	for(int i=0;i<=t+1;i++){
		for(int j=1;j<=n;j++){
			for(int k=1;k<=n;k++){
				idx[i][j][k] = id++;
			}
		}
	}
	id++;
	for(int i=1;i<=n;i++){
		scanf("%s", s2[i]+1);
	}
	queue<pii> q;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(s1[i][j] == 'Z'){
				q.push(pii(i, j));
				dp[i][j] = 0;
			}
		}
	}
	while(!q.empty()){
		int uy = q.front().first, ux = q.front().second;
		q.pop();
		for(int i=0;i<4;i++){
			int vy = uy+dir[i][0], vx = ux+dir[i][1];
			if(vy >= 1 && vy <= n && vx >= 1 && vx <= n && s1[vy][vx] != 'Y' && dp[vy][vx] == -1){
				dp[vy][vx] = dp[uy][ux] + 1;
				q.push(pii(vy, vx));
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(dp[i][j] == -1) dp[i][j] = 1e9;
			if(dp[i][j] > t) dp[i][j] = 1e9;
		}
	}
	int source = 0, sink = id-1;
	Dinic dinic(id);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(s1[i][j] >= '1' && s1[i][j] <= '9'){
				dinic.AddEdge(source, idx[0][i][j], s1[i][j]-'0');
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(s1[i][j] == 'Y' || s1[i][j] == 'Z') continue;
			for(int k=0;k<4;k++){
				int vy = i+dir[k][0], vx = j+dir[k][1];
				if(vy >= 1 && vy <= n && vx >= 1 && vx <= n && s1[vy][vx] != 'Y' && s1[vy][vx] != 'Z'){
					for(int x=0;x<t;x++){
						if(dp[vy][vx] >= x+1 && dp[i][j] > x){
							dinic.AddEdge(idx[x][i][j], idx[x+1][vy][vx], 1000);
						}
					}
				}
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(s1[i][j] == 'Y' || s1[i][j] == 'Z') continue;
			for(int x=0;x<=t;x++){
				if(s2[i][j] >= '1' && s2[i][j] <= '9'){
					dinic.AddEdge(idx[x][i][j], idx[t+1][i][j], s2[i][j]-'0');
				}
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(s1[i][j] == 'Y' || s1[i][j] == 'Z') continue;
			if(s2[i][j] >= '1' && s2[i][j] <= '9'){
				dinic.AddEdge(idx[t+1][i][j], sink, s2[i][j]-'0');
			}
		}
	}
	printf("%d\n", dinic.MaxFlow(source, sink));
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
typedef pair <int, string> pis;
#define f first
#define s second
#define mp make_pair
#define pb push_back
const int N = 11;
const int INF = 1e9;
const int SIZE = 2 * N * N;

struct edge
{
  int to, c, f, rev;
  edge() {}
  edge(int too, int cc, int ff, int revv)
  {
    to = too;
    c = cc;
    f = ff;
    rev = revv;
  }
};

vector <edge> g[SIZE];
int d[SIZE], ptr[SIZE], s, t, n;
queue <int> q;

void addEdge(int v, int u, int cap)
{
  g[v].pb(edge(u, cap, 0, 0));
  g[u].pb(edge(v, 0, 0, 0));
  g[v].back().rev = g[u].size() - 1;
  g[u].back().rev = g[v].size() - 1;
}
bool buildLevNet()
{
  for (int i = 0; i <= t; ++i)
    d[i] = INF;
  d[s] = 0;
  q.push(s);
  while (!q.empty())
  {
    int v = q.front();
    q.pop();
    for (int i = 0; i < g[v].size(); ++i)
    {
      int to = g[v][i].to;
      int cf = g[v][i].c - g[v][i].f;
      if (d[to] == INF && cf > 0)
      {
        d[to] = d[v] + 1;
        q.push(to);
      }
    }
  }
  return d[t] != INF;
}

int dfs(int v, int curFlow)
{
  if (v == t) return curFlow;
  for (int& i = ptr[v]; i < g[v].size(); ++i)
  {
    int to = g[v][i].to;
    int cf = g[v][i].c - g[v][i].f, addFlow;
    if (d[to] == d[v] + 1 && cf > 0 && (addFlow = dfs(to, min(curFlow, cf))))
    {
      g[v][i].f += addFlow;
      g[to][g[v][i].rev].f -= addFlow;
      return addFlow;
    }
  }
  return 0;
}

int dinica()
{
  int flow = 0;
  while (buildLevNet())
  {
    memset(ptr, 0, sizeof(ptr));
    int add;
    while ((add = dfs(s, INF)))
      flow += add;
  }
  return flow;
}

queue <pii> go;
const int X[] = {-1, 1, 0, 0};
const int Y[] = {0, 0, -1, 1};
int dst[N][N][N][N], tbad;
char a[N][N], b[N][N];
pii bad;
bool check(pii v)
{
  return v.f >= 0 && v.f < n && v.s >= 0 && v.s < n && a[v.f][v.s] != 'Y' && a[v.f][v.s] != 'Z';
}
void bfs(int xs, int ys)
{
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < n; ++j)
      dst[xs][ys][i][j] = INF;
  dst[xs][ys][xs][ys] = 0;
  go.push(mp(xs, ys));
  while (!go.empty())
  {
    pii v = go.front();
    go.pop();
    if (dst[xs][ys][v.f][v.s] == dst[bad.f][bad.s][v.f][v.s] && (bad.f != xs || bad.s != ys)) continue;
    for (int i = 0; i < 4; ++i)
    {
      pii nv = mp(v.f + X[i], v.s + Y[i]);
      if (check(nv) && dst[xs][ys][nv.f][nv.s] == INF && dst[xs][ys][v.f][v.s] + 1 <= dst[bad.f][bad.s][nv.f][nv.s])
      {
        dst[xs][ys][nv.f][nv.s] = dst[xs][ys][v.f][v.s] + 1;
        go.push(nv);
      }
    }
  }
}

int main()
{
  cin >> n >> tbad;
  int px, py;
  for (int i = 0; i < n; ++i)
    for (int j  = 0; j < n; ++j)
    {
      cin >> a[i][j];
      if (a[i][j] == 'Z') px = i, py = j;
    }
  for (int i = 0; i < n; ++i)
    for (int j  = 0; j < n; ++j)
      cin >> b[i][j];
  bad = mp(px, py);
  bfs(px, py);
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < n; ++j)
      dst[bad.f][bad.s][i][j] = min(dst[bad.f][bad.s][i][j], tbad);
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < n; ++j)
      if (check(mp(i, j))) bfs(i, j);
  s = 0;
  t = 2 * n * n + 1;
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < n; ++j)
    {
      if (a[i][j] != '0') addEdge(s, i * n + j + 1, a[i][j] - '0');
      if (b[i][j] != '0') addEdge(i * n + j + 1 + n * n, t, b[i][j] - '0');
    }
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < n; ++j)
      for (int i1 = 0; i1 < n; ++i1)
        for (int j1 = 0; j1 < n; ++j1)
          if (check(mp(i, j)) && check(mp(i1, j1)) && dst[i][j][i1][j1] <= dst[px][py][i1][j1])
            addEdge(i * n + j + 1, i1 * n + j1 + 1 + n * n, INF);
  cout << dinica();

/*
2 60
00
Z1

00
Z1
*/
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct networkflow{
    struct node{
        int v, w, rev;
    };
    void setEdge(int u, int v, int fl){
        int sz1= (int)adj[v].size();
        int sz2 = (int)adj[u].size();
        adj[u].push_back({v, fl, sz1});
        adj[v].push_back({u, 0, sz2});
    }
    vector<vector<node> > adj;
    vector<int> lev, edge_tried;
    int st, ed;
    networkflow(int V, int s, int t): adj(V), lev(V), edge_tried(V), st(s), ed(t){}
    bool assign_level(){
        fill(lev.begin(), lev.end(), -1);
        lev[st]=0;
        queue<int>que;que.push(st);
        while(!que.empty()){
            int now =que.front();que.pop();
            for(int i=0; i<adj[now].size(); i++){
                int nxt = adj[now][i].v;
                if(lev[nxt]==-1 && adj[now][i].w!=0){
                    lev[nxt] =  lev[now]+1;
                    que.push(nxt);
                }
            }
        }
        return (lev[ed]!=-1);
    }
    int dfs(int now, int fl){
        if(now==ed)return fl;
        for(int &i=edge_tried[now]; i<adj[now].size(); i++){
            int nxt = adj[now][i].v;
            if(lev[nxt]==lev[now]+1 && adj[now][i].w!=0){
                int nxtflow = dfs(nxt, min(fl, adj[now][i].w));
                if(nxtflow){
                    adj[now][i].w-=nxtflow;
                    adj[nxt][adj[now][i].rev].w+=nxtflow;
                    return nxtflow;
                }
            }
        }
        return 0;
    }
    ll dinic(){
        ll ret=0;
        while(assign_level()){
            fill(edge_tried.begin(), edge_tried.end(), 0);
            while(1){
                int amt = dfs(st, 2e9);
                if(amt==0)break;
                ret+=amt;
            }
        }
        return ret;
    }
};

int n, ti, ck[15][15];
string str[15], es[15];
int yy, xx;
int dy[]={1, -1, 0, 0};
int dx[]={0, 0, 1, -1};
void go()
{
    queue<pair<int, int> >que;que.push({yy, xx});
    ck[yy][xx]=1;
    int lev=1;
    while(!que.empty()){
        int sz = (int)que.size();
        for(int ite=0; ite<sz; ite++){
        pair<int, int> now = que.front();que.pop();
        for(int i=0; i<4; i++){
            int ny = now.first + dy[i];
            int nx = now.second + dx[i];
            if(!(ny>=0 && ny<n &&nx>=0 && nx<n))continue;
            if(ck[ny][nx] || str[ny][nx]=='Y')continue;
            ck[ny][nx] = lev;
            que.push({ny, nx});
        }
        }
        ++lev;
        lev=min(lev, ti);
    }
}
int table[15][15][65];
int main()
{
    cin>>n>>ti;
    for(int i=0; i<n; i++){
        cin>>str[i];
        for(int j=0 ;j<n; j++){
            if(str[i][j] =='Z'){
                    yy=i, xx=j;
            }
        }
    }
    getline(cin, str[n]);
    getline(cin, str[n]);

    for(int i=0; i<n; i++){
        cin>>es[i];
    }
    go();
    int nodecnt=0;

    for(int i=0; i<n; i++){
        for(int j=0 ;j<n; j++){
            if('0'<=str[i][j] &&str[i][j]<='9'){
                if(ck[i][j]==0)ck[i][j] = ti;
                for(int t =0; t<ck[i][j]; t++){
                    table[i][j][t]=++nodecnt;
                }
            }
            if('1'<=es[i][j] && es[i][j] <='9'){
                table[i][j][ck[i][j]]=++nodecnt;
            }
        }
    }

    int INF = (int)1e9;
    int st= 0, ed = nodecnt+3;
    networkflow net(nodecnt+5, st, ed);
    for(int i=0; i<n; i++){
        for(int j=0 ;j<n; j++){
             if('1'<=str[i][j] &&str[i][j]<='9'){
                    net.setEdge(st, table[i][j][0], str[i][j]-'0');
             }

             for(int ite=0; ite<4; ite++){
                int ny = i + dy[ite];
                int nx = j + dx[ite];
                if(!(ny>=0 && ny<n &&nx>=0 &&nx<n))continue;
                if(str[ny][nx]=='Y' || str[ny][nx]=='Z')continue;
                for(int t=0; ; t++){
                    if(table[i][j][t]==0)break;
                    if(t==ck[i][j] && es[i][j]>='1' && es[i][j]<='9')break;///마지막골인 가능하지만 뿌려선 안됨
                    if(table[ny][nx][t+1]){
                        net.setEdge(table[i][j][t], table[ny][nx][t+1], INF);
                    }
                }
             }

            if('1'<=es[i][j] &&es[i][j]<='9'){
                for(int t = 0; t<ck[i][j]; t++){
                    net.setEdge(table[i][j][t], table[i][j][t+1], INF);
                }
                net.setEdge(table[i][j][ck[i][j]], ed, es[i][j]-'0');
            }
        }
    }
    int ans = net.dinic();
    cout<<ans<<endl;

}


//http://codeforces.com/problemset/problem/78/E
//Evacuation

#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 from, to, rev, flow, cap;
    Aresta(){}
    Aresta(int _from, int _to, int _rev, int _flow, int _cap){
        from = _from; to = _to; rev = _rev; flow = _flow; cap = _cap;
    }
    int residuo() {return cap-flow;}
};

class EdmondsKarp {
public:
    int size;
    vector<Aresta*> *grafo;
    Aresta **prev;
    bool *vis;

    EdmondsKarp(int tam){
        size = tam;
        grafo = new vector<Aresta*>[size];
        prev = new Aresta*[size];
        vis = new bool[size];
    }

    void limpa(){
        for (int i=0; i<size; i++){
            for (size_t j=0; j<grafo[i].size(); j++){
                delete grafo[i][j];
            }
            grafo[i].clear();
        }
    }

    void destroy(){
        limpa();
        delete prev;
        delete vis;
        delete this;
    }

    void add(int s, int t, int cap){
        Aresta *a = new Aresta(s, t, grafo[t].size(), 0, cap);
        Aresta *b = new Aresta(t, 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(s, t, grafo[t].size(), 0, cap);
        Aresta *b = new Aresta(t, 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<size; i++){
            prev[i] = NULL;
            vis[i] = false;
        }

        queue<int> fila;
        fila.push(source);
        vis[source] = 1;

        int atual;
        while (!fila.empty()){
            atual = fila.front(); fila.pop();

            if (atual == sink) return true;

            for (Aresta *a : grafo[atual]){
                if (!vis[a->to] && a->residuo() > 0){
                    prev[a->to] = a;
                    vis[a->to] = true;
                    fila.push(a->to);
                }
            }
        }

        return false;
    }

    int dfs(int source, int sink){
        int flow = INT_MAX;
        int v = sink;
        while (v != source){
            flow = min(flow, prev[v]->residuo());
            v = prev[v]->from;
        }

        v = sink;
        Aresta *a;
        while (v != source){
            a = prev[v];
            a->flow += flow;
            grafo[a->to][a->rev]->flow -= flow;
            v = a->from;
        }
        return flow;
    }

    long long int flow(int source, int sink){
        int flow = 0;
        while (bfs(source, sink)){
            flow += dfs(source, sink);
        }
        return flow;
    }
};

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};  //^<v>
int moveY[] = {0, -1, 0, 1};  //^<v>

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);
            }
        }
    }

    EdmondsKarp *din = new EdmondsKarp(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("%lld\n", din->flow(0, sink));
    delete din;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());

#define int long long
#define ll long long
#define mp make_pair
#define f first
#define s second
#define pii pair<int, int>
#define all(_v) _v.begin(), _v.end()
#define sz(a) ((int)a.size())
#define what_is(x) cout << #x << " is " << x << endl;
typedef long double ld;

const ll inf = 1e17 + 7;
const int max_n = 1001;

int xdir[]{0, 0, -1, 1}, ydir[]{-1, 1, 0, 0};

vector<int> gr[max_n];
bool used[max_n];
int pa[max_n];

bool check(int x, int y, vector<string>& s) {
    return x >= 0 && y >= 0 && x < s.size() && y < s.size() && s[x][y] != 'Y' && s[x][y] != 'Z';
}

vector<vector<int>> bfs(int st_x, int st_y, vector<string> s) {
    vector<vector<int>> res(s.size(), vector<int>(s.size(), inf));
    res[st_x][st_y] = 0;
    deque<pii> b;
    b.emplace_back(st_x, st_y);

    while(b.size()) {
        pii v = b.front();
        b.pop_front();

        for(int i = 0;i < 4;i++) {
            int x = v.f + xdir[i];
            int y = v.s + ydir[i];
            if (!check(x, y, s) || res[x][y] != inf) continue;

            res[x][y] = res[v.f][v.s] + 1;
            b.emplace_back(x, y);
        }
    }

    return res;
}

void scan() {
    int n, t;
    cin >> n >> t;
    vector<string> s1(n), s2(n);
    for(int i = 0;i < n;i++)
        cin >> s1[i];

    for(int i = 0;i < n;i++)
        cin >> s2[i];

    int x_reac, y_reac;
    for(int i = 0;i < n;i++) {
        for(int j = 0;j < n;j++) {
            if (s1[i][j] == 'Z') {
                x_reac = i;
                y_reac = j;
            }
        }
    }

    vector<vector<int>> reac = bfs(x_reac, y_reac, s1);

    for(int i = 0;i < n;i++) {
        for(int j = 0;j < n;j++) {
            if (!check(i, j, s1)) continue;
            vector<vector<int>> a = bfs(i, j, s1);

            for(int x = 0;x < n;x++) {
                for(int y = 0;y < n;y++) {
                    if (!check(x, y, s1) || a[x][y] > t || a[x][y] > reac[x][y]) continue;

                    if (a[x][y] == reac[x][y]) {
                        bool good = false;
                        for(int id = 0;id < 4;id++) {
                            int xto = x + xdir[id];
                            int yto = y + ydir[id];
                            if (!check(xto, yto, s1) ||  a[xto][yto] >= reac[xto][yto]) continue;
                            good = true;
                        }
                        if (!good) continue;
                    }

                    for(int num1 = 1;num1 <= s1[i][j] - '0';num1++) {
                        for(int num2 = 1;num2 <= s2[x][y] - '0';num2++) {
                            gr[10 * (j + i * 10) + num1].emplace_back(10 * (y + 10 * x) + num2);
                        }
                    }
                }
            }
        }
    }
}

bool kuhn(int v) {
    if (used[v]) return false;
    used[v] = true;
    for(int to : gr[v]) {
        if (pa[to] == 0 || kuhn(pa[to])) {
            pa[to] = v;
            return true;
        }
    }
    return false;
}

void solve() {
    scan();

    int n = max_n;

    for(int i = 0;i < n;i++) {
        kuhn(i);
        for(int j = 0;j < n;j++)
            used[j] = false;
    }

    int res = 0;
    for(int i = 0;i < n;i++) res += pa[i] != 0;

    cout << res;
}

signed main() {
    cin.tie(0);
    cout.tie(0);
    ios_base::sync_with_stdio(0);
    cout.precision(10);

    solve();
}


//In the name of God

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

template<class P, class Q> inline P smin(P &a, Q b) { if (b < a) a = b; return a; }
template<class P, class Q> inline P smax(P &a, Q b) { if (a < b) a = b; return a; }

#define rep(i, n) for (int i = 0, _n = (int)(n); i < _n; i++)

const int N = 205, M = N * N;
#define prev some

int read() { int x; cin >> x; return x; }

int prev[M], mark[N], head[N], from[M], cap[M], to[M], ec, a[N][N], b[N][N], red[N][N], block[N][N], dis[N][N], cnt, dred[N], seen[N];
pair<int, int> q[N];
int dx[4] = {0, -1, 0, 1};
int dy[4] = {1, 0, -1, 0};

void add_edge(int u, int v, int uv, int vu) {
	from[ec] = u, to[ec] = v, cap[ec] = uv, prev[ec] = head[u], head[u] = ec++;
	from[ec] = v, to[ec] = u, cap[ec] = vu, prev[ec] = head[v], head[v] = ec++;
}

int dfs(int v, int sink, int flow = 2e9) {
	if (v == sink)
		return flow;
	if (mark[v]++)
		return 0;
	for (int e = head[v]; ~e; e = prev[e]) if (cap[e]) {
		int u = to[e];
		int x = dfs(u, sink, min(flow, cap[e]));
		if (x) {
			cap[e] -= x;
			cap[e ^ 1] += x;
			return x;
		}
	}
	return 0;
}

int max_flow(int source, int sink) {
	int res = 0;
	while (true) {
		memset(mark, 0, sizeof mark);
		int add = dfs(source, sink);
		res += add;
		if (!add)
			break;
	}
	return res;
}

int32_t main() {
	ios_base :: sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int n = read(), dt = read();
	memset(head, -1, sizeof head);
	memset(dis, 63, sizeof dis);
	rep(i, N)
		dis[i][i] = 0;
	rep(x, n)
		rep(y, n) {
			char foo;
			cin >> foo;
			if (foo == 'Y')
				block[x][y] = 1;
			else if (foo == 'Z')
				red[x][y] = 1;
			else
				a[x][y] = foo - '0';
		}
	rep(x, n)
		rep(y, n) {
			char foo;
			cin >> foo;
			if (foo != 'Y' && foo != 'Z') {
				b[x][y] = foo - '0';
				rep(d, 4) {
					int i = x + dx[d], j = y + dy[d];
					if (i >= 0 && j >= 0 && i < n && j < n && !block[i][j] && !red[i][j]) {
						dis[x * n + y][i * n + j] = 1;
					}
				}
			}
		}
	int m = n * n;
	rep(k, m)
		rep(i, m)
			rep(j, m)
				if (dis[i][k] + dis[k][j] < dis[i][j])
					dis[i][j] = dis[i][k] + dis[k][j];
	int h = 0, t = 0;
	memset(dred, 63, sizeof dred);
	rep(i, n)
		rep(j, n)
			if (red[i][j]) {
				q[t++] = {i, j};
				dred[i * n + j] = 0;
			}
	while (h != t) {
		auto cur = q[h++];
		int x = cur.first, y = cur.second;
		rep(d, 4) {
			int i = x + dx[d], j = y + dy[d];
			if (i >= 0 && j >= 0 && i < n && j < n && !block[i][j] && !red[i][j] && dred[i * n + j] > 1e9) {
				dred[i * n + j] = dred[x * n + y] + 1;
				q[t++] = {i, j};
			}
		}
	}
	int sink = N - 1, source = N - 2;
	rep(cur, m) {
		memset(seen, 0, sizeof seen);
		h = 0;
		t = 0;
		int sx = cur / n, sy = cur % n;
		if (block[sx][sy] || red[sx][sy])
			continue;
		q[t++] = {sx, sy};
		seen[cur] = 1;
		while (h != t) {
			int x = q[h].first, y = q[h++].second;
			if (dis[cur][x * n + y] <= dt)
				add_edge(cur << 1, (x * n + y) << 1 | 1, 1000, 0);
			if (dis[cur][x * n + y] == dred[x * n + y])
				continue;
			rep(d, 4) {
				int i = x + dx[d], j = y + dy[d], id = i * n + j;
				if (i >= 0 && j >= 0 && i < n && j < n && !block[i][j] && !red[i][j] && dis[cur][id] <= dred[id] && dis[cur][id] <= dt && dis[cur][id] > dis[cur][x * n + y] && !seen[id]) {
					q[t++] = {i, j};
					seen[id] = 1;
				}
			}
		}
	}
	rep(i, m)
		add_edge(source, i << 1, a[i / n][i % n], 0);
	rep(i, m)
		add_edge(i << 1 | 1, sink, b[i / n][i % n], 0);
	cout << max_flow(source, sink);
}


#include <bits/stdc++.h>

using namespace std;

#define pii pair<int, int>
#define MP make_pair
#define LL long long
#define ls (i << 1)
#define rs (ls | 1)
#define md (ll + rr >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define eps 1e-8
#define inf 0x3f3f3f3f
#define mod 1000000007
#define N 410
#define M 200020
#define fi first
#define se second

char buf[32000000],*pt = buf,*o = buf;
int getint(){
    int f = 1,x = 0;
    while((*pt != '-') && (*pt < '0' || *pt > '9'))    pt ++;
    if(*pt == '-')    f = -1,pt ++;    else    x = *pt++ - 48;
    while(*pt >= '0' && *pt <= '9')    x = x * 10 + *pt ++ - 48;
    return x * f;
}
char getch(){
    char ch;
    while(*pt < 'A' || *pt > 'Z')    pt ++;
    ch=*pt;pt++;
    return ch;
}

struct dinic{
	int fst[N], vv[M], nxt[M], cap[M], flow[M], e;
	int d[N], cur[N];
	int s, t;
	void init(){
		memset(fst, -1, sizeof fst); e = 0;
	}
	void add(int u, int v, int c){
		vv[e] = v, nxt[e] = fst[u], cap[e] = c, flow[e] = 0, fst[u] = e++;
		vv[e] = u, nxt[e] = fst[v], cap[e] = 0, flow[e] = 0, fst[v] = e++;
	}
	bool bfs(){
	   	memset(d, -1, sizeof d);
   	   	d[s] = 0;
		queue<int> q;
		q.push(s);
		while(!q.empty()){
			int u = q.front(); q.pop();
			for(int i = fst[u]; ~i; i = nxt[i]){
				int v = vv[i];
				if(d[v] == -1 && cap[i] > flow[i]){
					d[v] = d[u] + 1;
					q.push(v);
				}
			}
		}
		return d[t] != -1;
	}
	int dfs(int u, int a){
		if(u == t || a == 0) return a;
		int ret = 0, f;
		for(int &i = cur[u]; ~i; i = nxt[i]){
			int v = vv[i];
			if(d[v] == d[u] + 1 && (f = dfs(v, min(a, cap[i] - flow[i]))) > 0){
				a -= f;
				ret += f;
				flow[i] += f;
				flow[i^1] -=f;
				if(a == 0) break;
			}
		}
		return ret;
	}
	int gao(int _s, int _t){
		s = _s, t = _t;
		int ret = 0;
		while(bfs()){
			memcpy(cur, fst, sizeof fst);
			ret += dfs(s, inf);
		}
		return ret;
	}
}go;
int d[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1};
int dis[12][12], tim[12][12];
char g[N][N], h[N][N];
int n, t;
bool in(int x, int y){
	return x >= 0 && x < n && y >= 0 && y < n;
}
void bfs1(int sx, int sy){
	memset(tim, 0x3f, sizeof tim);
	queue<int> q;
	q.push(sx * 10 + sy);
	tim[sx][sy] = 0;
	while(!q.empty()){
		int x = q.front() / 10, y = q.front() % 10;
	   	q.pop();
		for(int i = 0; i < 4; ++i){
			int nx = x + d[i][0], ny = y + d[i][1];
			if(in(nx, ny) && g[nx][ny] >= '0' && g[nx][ny] <= '9' && tim[nx][ny] > tim[x][y] + 1){
				tim[nx][ny]	= tim[x][y] + 1;
				q.push(nx * 10 + ny);
			}
		}
	}
}
void bfs2(int sx, int sy){
	memset(dis, 0x3f, sizeof dis);
	queue<int> q;
	q.push(sx * 10 + sy);
	dis[sx][sy] = 0;
	while(!q.empty()){
		int x = q.front() / 10, y = q.front() % 10;
		q.pop();
		for(int i = 0; i < 4; ++i){
			int nx = x + d[i][0], ny = y + d[i][1];
			if(in(nx, ny) && h[nx][ny] >= '0' && h[nx][ny] <= '9' && dis[nx][ny] > dis[x][y] + 1){
				if(h[nx][ny] >= '0' && tim[nx][ny] >= dis[x][y] + 1){
					dis[nx][ny] = dis[x][y] + 1;
					if(tim[nx][ny] > dis[nx][ny])
						q.push(nx * 10 + ny);
				}
			}
		}
	}
}
int main(){
	scanf("%d%d", &n, &t);
	for(int i = 0; i < n; ++i)
		scanf("%s", g[i]);
	for(int i = 0; i < n; ++i)
		scanf("%s", h[i]);
	for(int i = 0; i < n; ++i)
		for(int j = 0; j < n; ++j)
			if(g[i][j] == 'Z')
				bfs1(i, j);
	int S = 0, T = n * n * 2 + 1;
	go.init();
	for(int i = 0; i < n; ++i)
		for(int j = 0; j < n; ++j){
			if(g[i][j] > '0' && g[i][j] <= '9')
				go.add(S, i * n + j + 1, g[i][j] - '0');
			if(h[i][j] > '0' && h[i][j] <= '9')
				go.add(n * n + i * n + j + 1, T, h[i][j] - '0');
		}
	for(int i = 0; i < n; ++i)
		for(int j = 0; j < n; ++j)
			if(g[i][j] > '0' && g[i][j] <= '9'){
				bfs2(i, j);
				for(int x = 0; x < n; ++x)
					for(int y = 0; y < n; ++y){
						if(h[x][y] > '0' && h[x][y] <= '9' && dis[x][y] <= t){
							go.add(i * n + j + 1, n * n + x * n + y + 1, inf);
						}
					}
			}
	int ret = go.gao(S, T);
	printf("%d\n", ret);
	return 0;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <vector>
#include <deque>
using namespace std;
vector<int> e[2020];
int ir[20][20];
int sc[20][20];
int pc[20][20];
char s[20][20];
char p[20][20];
int dd[20][20];
int dx[5]={0,1,-1,0};
int dy[5]={1,0,0,-1};
vector<int> ns[20][20],np[20][20];
void ade(int a,int b)
{
    e[a].push_back(b);
    e[b].push_back(a);
}
int ds[2020];
int pa[2020];
int sp,pp;
bool bfs()
{
    deque<int> q;
    for(int i=1;i<=sp;i++)
    {
        if(pa[i]==0)
            ds[i]=0,q.push_back(i);
        else
            ds[i]=3010;
    }
    ds[0]=3010;
    while(!q.empty())
    {
        int u=q[0];
        q.pop_front();
        if(ds[u]<ds[0])
        {
            for(int i=0;i<e[u].size();i++)
            {
                int v=pa[e[u][i]];
                if(ds[v]>ds[u]+1)
                    ds[v]=ds[u]+1,q.push_back(v);
            }
        }
    }
    return ds[0]!=3010;
}
bool dfs(int x)
{
    if(x==0)
        return 1;
    for(int i=0;i<e[x].size();i++)
    {
        int u=pa[e[x][i]];
        if(ds[u]==ds[x]+1)
        {
            if(dfs(u))
            {
                pa[x]=e[x][i];
                pa[e[x][i]]=x;
                return 1;
            }
        }
    }
    return 0;
}
int hkp()
{
    int an=0;
    while(bfs())
    {
        for(int i=1;i<=sp;i++)
        {
            if(pa[i]==0)
                an+=dfs(i);
        }
    }
    return an;
}
int n,t;
void wk(int a,int b)
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            dd[i][j]=100000;
        }
    }
    deque<pair<int,int> > q;
    dd[a][b]=0;
    q.push_back(make_pair(a,b));
    while(!q.empty())
    {
        int x=q[0].first,y=q[0].second;
        q.pop_front();
        for(int i=0;i<np[x][y].size();i++)
            for(int j=0;j<ns[a][b].size();j++)
                ade(ns[a][b][j],np[x][y][i]);
        if(dd[x][y]==ir[x][y])
            continue;
        for(int d=0;d<4;d++)
        {
            int nx=x+dx[d];
            int ny=y+dy[d];
            if(sc[nx][ny]!=-1&&dd[nx][ny]>dd[x][y]+1&&dd[x][y]+1<=ir[nx][ny])
            {
                dd[nx][ny]=dd[x][y]+1;
                q.push_back(make_pair(nx,ny));
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&t);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            ir[i][j]=t;
    for(int i=1;i<=n;i++)
        scanf("%s",s[i]+1);
    for(int i=1;i<=n;i++)
        scanf("%s",p[i]+1);
    int rx,ry;
    sp=1,pp=1000;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(s[i][j]=='Z'||s[i][j]=='Y')
                sc[i][j]=-1,ir[i][j]=0;
            if(s[i][j]=='Z')
                rx=i,ry=j,ir[i][j]=0;
            if('0'<=s[i][j]&&s[i][j]<='9')
                sc[i][j]=s[i][j]-'0';
            for(int k=0;k<sc[i][j];k++)
                ns[i][j].push_back(sp++);
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if('0'<=p[i][j]&&p[i][j]<='9')
                pc[i][j]=p[i][j]-'0';
            for(int k=0;k<pc[i][j];k++)
                np[i][j].push_back(pp++);
        }
    }
    deque<pair<int,int> > q;
    q.push_back(make_pair(rx,ry));
    while(!q.empty())
    {
        rx=q[0].first,ry=q[0].second;
        q.pop_front();
        int nx,ny;
        for(int d=0;d<4;d++)
        {
            nx=rx+dx[d];
            ny=ry+dy[d];
            if(ir[nx][ny]>ir[rx][ry]+1&&sc[nx][ny]!=-1)
            {
                ir[nx][ny]=ir[rx][ry]+1;
                q.push_back(make_pair(nx,ny));
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(sc[i][j]>0)
            {
                wk(i,j);
            }
        }
    }
    printf("%d",hkp());
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
using namespace std;
#define INF 10000000
#define N 210
#define M 21000
struct Edge{
    int v,w;
}edge[M];
int adj[M],head[N],e;
void addedge(int u,int v,int w){
    edge[e].v=v;edge[e].w=w;adj[e]=head[u];head[u]=e++;
    edge[e].v=u;edge[e].w=0;adj[e]=head[v];head[v]=e++;
}
int S,T;

int dist[N],q[N*2],arc[N],gap[N],inq[N],pre[N];
int SAP(int s,int t){
    memset(arc,-1,sizeof(arc));
    memset(pre,-1,sizeof(pre));
    int qf=0,qr=0;
    q[qr++]=t;inq[t]=1;gap[0]++;dist[t]=0;
    while(qf<qr){
        int u=q[qf++];
        for(int i=head[u];i!=-1;i=adj[i])
            if(!inq[edge[i].v]){
            int v=edge[i].v;
            q[qr++]=v;
            inq[v]=1;
            dist[v]=dist[u]+1;
            gap[dist[v]]++;
            arc[v]=head[v];
        }
    }
    int low=INF,u=s,ans=0;
    pre[s]=s;
    while(dist[s]<t){
        bool flag=false;
        for(int &i=arc[u];i!=-1;i=adj[i])
            if(edge[i].w && dist[edge[i].v]+1==dist[u]){
            flag=true;
            low=min(low,edge[i].w);
            pre[edge[i].v]=u;
            u=edge[i].v;
            if(u==t){
                while(u!=s){
                    u=pre[u];
                    edge[arc[u]].w-=low;
                    edge[arc[u]^1].w+=low;
                }
                ans+=low;
                low=INF;
            }
            break;
        }
        if(flag)
            continue;
        int mindis=t+1;
        for(int i=head[u];i!=-1;i=adj[i])
            if(edge[i].w && mindis>dist[edge[i].v]){
           mindis=dist[edge[i].v];
           arc[u]=i;
        }
        gap[dist[u]]--;
        if(gap[dist[u]]==0)
            return ans;
        dist[u]=mindis+1;
        gap[dist[u]]++;
        u=pre[u];
    }
    return ans;
}

char str[12][12],str2[12][12];
int sci[12][12],ca[12][12],stone[62][12][12];
int dp[62][12][12][12][12];
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int n,t;

void expand(){
    for(int k=1;k<=t;++k)
        for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j){
        if(stone[k-1][i][j]==1)
            stone[k][i][j]=1;
        else if(stone[k-1][i][j]==2)
            stone[k][i][j]=2;
        else{
            int nx,ny;
            for(int z=0;z<4;++z){
                nx=i+dir[z][0];
                ny=j+dir[z][1];
                if(nx>=1&&nx<=n&&ny>=1&&ny<=n){
                    if(stone[k-1][nx][ny]==2)
                        stone[k][i][j]=2;
                }
            }
        }
    }
}
int vis[12][12];
void dfs(int x,int y,int nowx,int nowy,int k){
    vis[nowx][nowy]=1;
    dp[k][x][y][nowx][nowy]=1;
    if(k>=t || stone[k][nowx][nowy])
        return;
    int nx,ny;
    for(int z=0;z<4;++z){
        nx=nowx+dir[z][0];
        ny=nowy+dir[z][1];
        if(nx>=1&&nx<=n&&ny>=1&&ny<=n && !vis[nx][ny]){
            if(stone[k][nx][ny])
                continue;
            dfs(x,y,nx,ny,k+1);
        }
    }
}
int main (){
    scanf("%d%d",&n,&t);
    for(int i=1;i<=n;++i){
        scanf("%s",str[i]+1);
        for(int j=1;j<=n;++j){
            if(str[i][j]=='Z')
                stone[0][i][j]=2;
            else if(str[i][j]=='Y')
                stone[0][i][j]=1;
            else sci[i][j]=str[i][j]-'0';
        }
    }
    for(int i=1;i<=n;++i){
        scanf("%s",str2[i]+1);
        for(int j=1;j<=n;++j){
            if(str2[i][j]>='0' && str2[i][j]<='9')
                ca[i][j]=str2[i][j]-'0';
        }
    }

    expand();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
        if(sci[i][j]){
        memset(vis,0,sizeof(vis));
        dfs(i,j,i,j,0);
    }
    for(int k=1;k<=t;++k)
        for(int x=1;x<=n;++x)
            for(int y=1;y<=n;++y)
            for(int nx=1;nx<=n;++nx)
            for(int ny=1;ny<=n;++ny)
        {
            dp[k][x][y][nx][ny]+=dp[k-1][x][y][nx][ny];
        }
    S=0;T=n*n*2+1;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
        addedge(S,(i-1)*n+j,sci[i][j]);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
        addedge(n*n+(i-1)*n+j,T,ca[i][j]);
    for(int x=1;x<=n;++x)
        for(int y=1;y<=n;++y)
        for(int nx=1;nx<=n;++nx)
        for(int ny=1;ny<=n;++ny)
            if(sci[x][y] && ca[nx][ny]){
        if(dp[t][x][y][nx][ny])
        addedge((x-1)*n+y,n*n+(nx-1)*n+ny,INF);
    }
    int ans=SAP(S,T);
    printf("%d\n",ans);
    return 0;
}


///****In the name of Allah, most Gracious, most Compassionate****//

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair <int, int> pii;

#define ALL(a) a.begin(), a.end()
#define FastIO ios::sync_with_stdio(false); cin.tie(nullptr);cout.tie(nullptr)
#define IN freopen("input.txt","r+",stdin)
#define OUT freopen("output.txt","w+",stdout)

#define TEST

#ifdef TEST
#define DBG(a) cout<< #a <<" --> "<<(a)<<endl;
#define NL cout<<"\n";
#else
#define DBG(a) ;
#define NL cout<<"\n";
#endif // TEST

template < class T1,class T2>
ostream &operator <<(ostream &os,const pair < T1,T2 > &p)
{
    os<<"{"<<p.first<<","<<p.second<<"}";
    return os;
}

/*
	Push Relabel O(n^3) implimentation using FIFO method to chose push vertex.
	This uses gapRelabel heuristic to fasten the process even further. If only
	the maxFlow value is required then the algo can be stopped as soon as the
	gap relabel method is called. However, to get the actual flow values in the
	edges, we need to let the algo terminate itself.

	This implimentation assumes zero based vertex indexing. Edges to the graph
	can be added using the addEdge method only. capacity for residual edges is
	set to be zero. To get the actual flow values iterate through the edges and
	check for flow for an edge with cap > 0.

	This implimentaion is superior over dinic's for graphs where graph is dense
	locally at some places and mostly sparse. For randomly generated graphs, this
	implimentation gives results within seconds for n = 10000 nodes, m = 1000000
	edges.

	Code Tested on : SPOJ FASTFLOW
	@author : triveni
*/

typedef int fType;

struct edge
{
    int from, to;
    fType cap, flow;
    edge(int from, int to, fType cap, fType flow = 0) : from(from), to(to), cap(cap), flow(flow) {}
};

struct PushRelabel
{
    int N;
    vector<edge> edges;
    vector<vector<int> > G;
    vector<int> h, inQ, count;
    vector<fType> excess;
    queue<int> Q;
    PushRelabel(int N) : N(N), count(N<<1), G(N), h(N), inQ(N), excess(N) {}

    int addEdge(int from, int to, int cap)
    {
        G[from].push_back(edges.size());
        edges.push_back(edge(from, to, cap));
        G[to].push_back(edges.size());
        edges.push_back(edge(to, from, 0));
        return G[from].back();
    }

    void enQueue(int u)
    {
        if(!inQ[u] && excess[u] > 0) Q.push(u), inQ[u] = true;
    }

    void Push(int edgeIdx)
    {
        edge & e = edges[edgeIdx];
        int toPush = min<fType>(e.cap - e.flow, excess[e.from]);
        if(toPush > 0 && h[e.from] > h[e.to])
        {
            e.flow += toPush;
            excess[e.to] += toPush;
            excess[e.from] -= toPush;
            edges[edgeIdx^1].flow -= toPush;
            enQueue(e.to);
        }
    }

    void Relabel(int u)
    {
        count[h[u]] -= 1;
        h[u] = 2*N-2;
        for (int i = 0; i < G[u].size(); ++i)
        {
            edge & e = edges[G[u][i]];
            if(e.cap > e.flow) h[u] = min(h[u], h[e.to]);
        }
        count[++h[u]] += 1;
    }

    void gapRelabel(int height)
    {
        for (int u = 0; u < N; ++u) if(h[u] >= height && h[u] < N)
            {
                count[h[u]] -= 1;
                count[h[u] = N] += 1;
                enQueue(u);
            }
    }

    void Discharge(int u)
    {
        for (int i = 0; excess[u] > 0 && i < G[u].size(); ++i)
        {
            Push(G[u][i]);
        }
        if(excess[u] > 0)
        {
            if(h[u] < N && count[h[u]] < 2) gapRelabel(h[u]);
            else Relabel(u);
        }
        else if(!Q.empty())   // dequeue
        {
            Q.pop();
            inQ[u] = false;
        }
    }

    fType getFlow(int src, int snk)
    {
        h[src] = N;
        inQ[src] = inQ[snk] = true;
        count[0] = N - (count[N] = 1);
        for (int i = 0; i < G[src].size(); ++i)
        {
            excess[src] += edges[G[src][i]].cap;
            Push(G[src][i]);
        }
        while (!Q.empty())
        {
            Discharge(Q.front());
        }
        return excess[snk];
    }
};

const int N=20+5;
const int oo=1e4+7;
int dis[N][N];
string s[N];
string t[N];
int n,k;
int dx[]= {1,0,-1,0};
int dy[]= {0,1,0,-1};

vector<pii> source,sink;

int sinkid[N][N];

void bfs(int x,int y)
{
    memset(dis, -1, sizeof dis);
    queue<pii> q;
    dis[x][y]= 0;
    q.push({x,y});

    while(!q.empty())
    {
        x=  q.front().first;
        y=  q.front().second;

        q.pop();

        for(int j=0; j<4; j++)
        {
            int xx =x+dx[j];
            int yy =y+dy[j];

            if(xx<0 or xx>= n)
                continue;
            if(yy<0 or yy>= n)
                continue;

            if(dis[xx][yy] !=-1 )
                continue;

            if(t[xx][yy]=='Y' or t[xx][yy]=='Z')
                continue;
            dis[xx][yy]= dis[x][y]+1;
            q.push({xx,yy});
        }
    }
}

int dp[65][12][12][12][12];

int pos(int t,int x0,int y0, int x,int y)
{
    if(dis[x0][y0]< t) return 0;
    if(x0==x and y0==y) return 1;

    if(t>=k) return 0;

    if(dis[x0][y0]<=t) return 0;

    if(dp[t][x0][y0][x][y]!=-1) return dp[t][x0][y0][x][y];

    for(int j=0; j<4; j++)
    {
        int xx = x0+dx[j];
        int yy = y0+dy[j];

        if(xx<0 or xx>= n)
            continue;
        if(yy<0 or yy>= n)
            continue;
        if(s[xx][yy]=='Y') continue;
        if(s[xx][yy]=='Z') continue;

        if(pos(t+1 , xx ,yy , x , y)) return dp[t][x0][y0][x][y]=1;
    }
    return dp[t][x0][y0][x][y]=0;
}

int32_t main()
{
    //FastIO;

    memset(dp , -1 , sizeof dp);
    cin>>n>>k;
    for(int i=0; i<n; i++)
        cin>>s[i];
    for(int i=0; i<n; i++)
        cin>>t[i];
    int x= -1, y = -1 ;
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
            if(t[i][j]== 'Z')
                x= i, y = j;
    }
    bfs(x,y);
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++) dis[i][j] = dis[i][j]==-1 ? oo : dis[i][j];
    }

//    for(int i=0; i<n; i++)
//    {
//        for(int j=0; j<n; j++)
//            printf("%7d ",dis[i][j]);
//        NL;
//    }
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            char c = s[i][j];
            if(c=='Z')
                continue;
            if(c=='Y')
                continue;
            if(c=='0')
                continue;
            source.push_back({i,j});
        }
    }
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            char c = t[i][j];
            if(c=='Z')
                continue;
            if(c=='Y')
                continue;
            if(c=='0')
                continue;
            sink.push_back({i,j});
        }
    }
//    DBG(source.size());
//    DBG(sink.size());

//    for(pii i: source )
//    {
//        for(pii j: sink)
//        {
//            if(pos(0 , i.first  , i.second , j.first , j.second))  { DBG(i);DBG(j);NL; }
//        }
//    }
    PushRelabel g(source.size()  + sink.size()  + 2);
    for(int i=0;i<source.size();i++) g.addEdge(0,i+1 , s[source[i].first][source[i].second]-'0');
    for(int i=0;i<sink.size();i++) g.addEdge(source.size() + i+1  ,source.size()  + sink.size()  + 1,  t[sink[i].first][sink[i].second]-'0');
    for(int i=0;i<source.size();i++)
    {
        for(int j=0;j<sink.size();j++)
        {
            if(pos(0,source[i].first  , source[i].second , sink[j].first , sink[j].second))
                g.addEdge(i+1 , source.size()+j+1 , oo);
        }
    }
    cout<<g.getFlow(0,source.size() + sink.size() + 1);
}


/****************************************
**     Solution by Bekzhan Kassenov    **
****************************************/

#include <bits/stdc++.h>

using namespace std;

#define F first
#define S second
#define MP make_pair
#define all(x) (x).begin(), (x).end()

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

const double EPS = 1e-9;
const double PI = acos(-1.0);
const int MOD = 1000 * 1000 * 1000 + 7;
const int INF = 2000 * 1000 * 1000;
const int MAXN = 210;
const int MAXM = 2 * MAXN * MAXN;
const int dx[] = {1, 0, 0, -1};
const int dy[] = {0, 1, -1, 0};
const int S = MAXN - 2;
const int T = MAXN - 1;

template <typename T>
inline T sqr(T n) {
    return n * n;
}

struct MaxFlow {
    int to[MAXM];
    int flow[MAXM], cap[MAXM];
    int lastEdge;

    vector <int> g[MAXN];

    bool used[MAXN];

    MaxFlow() : lastEdge(0) { }

    void addEdge(int from, int to, int cap) {
        this->to[lastEdge] = to;
        this->flow[lastEdge] = 0;
        this->cap[lastEdge] = cap;
        g[from].push_back(lastEdge++);

        this->to[lastEdge] = from;
        this->flow[lastEdge] = 0;
        this->cap[lastEdge] = 0;
        g[to].push_back(lastEdge++);
    }

    bool dfs(int v, int T, int curFlow) {
        if (v == T) {
            return true;
        }

        used[v] = true;

        for (int idx: g[v]) {
            if (!used[to[idx]] && cap[idx] - flow[idx] >= curFlow &&
                dfs(to[idx], T, curFlow)) {

                flow[idx] += curFlow;
                flow[idx ^ 1] -= curFlow;

                return true;
            }
        }

        return false;
    }

    int getMaxFlow(int S, int T) {
        int curFlow = 1 << 30;
        int resFlow = 0;

        while (curFlow > 0) {
            if (dfs(S, T, curFlow)) {
                resFlow += curFlow;
            } else {
                curFlow >>= 1;
            }

            memset(used, false, sizeof used);
        }

        return resFlow;
    }
};

MaxFlow maxFlow;

int n, t;
char a[15][15];
char b[15][15];
int dist[15][15];
bool used[15][15];

bool ok(int x, int y) {
    return 0 <= x && x < n &&
           0 <= y && y < n &&
           a[x][y] != 'Y' &&
           a[x][y] != 'Z';
}

void bfsDeath(int x, int y) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            dist[i][j] = INF;
        }
    }

    queue <int> X, Y;
    dist[x][y] = 0;
    X.push(x);
    Y.push(y);

    while (!X.empty()) {
        assert(!Y.empty());

        int curx = X.front();
        int cury = Y.front();

        X.pop();
        Y.pop();

        for (int k = 0; k < 4; k++) {
            int tx = curx + dx[k];
            int ty = cury + dy[k];

            if (ok(tx, ty) && dist[tx][ty] == INF) {
                dist[tx][ty] = dist[curx][cury] + 1;
                X.push(tx);
                Y.push(ty);
            }
        }
    }
}

void runBFS(int x, int y) {
    queue <int> X, Y, lev;
    memset(used, false, sizeof used);

    used[x][y] = true;
    X.push(x);
    Y.push(y);
    lev.push(0);

    while (!X.empty()) {
        assert(!Y.empty());

        int curx = X.front();
        int cury = Y.front();
        int curlev = lev.front();

        X.pop();
        Y.pop();
        lev.pop();

        if (isdigit(b[curx][cury]) && b[curx][cury] != '0') {
            maxFlow.addEdge(x * n + y, sqr(n) + 1 + curx * n + cury, INF);
        }

        if (curlev >= t) {
            continue;
        }

        for (int k = 0; k < 4; k++) {
            int tx = curx + dx[k];
            int ty = cury + dy[k];

            if (ok(tx, ty) && !used[tx][ty]) {
                if (dist[tx][ty] > curlev + 1) {
                    X.push(tx);
                    Y.push(ty);

                    lev.push(curlev + 1);
                } else if (dist[tx][ty] > curlev && isdigit(b[tx][ty]) && b[tx][ty] != '0') {
                    maxFlow.addEdge(x * n + y, sqr(n) + 1 + tx * n + ty, INF);
//                    printf("(%d, %d) --> (%d, %d)\n", x, y, tx, ty);
                }

                used[tx][ty] = true;
            }
        }
    }
}

void build() {

    int posi = -1, posj = -1;
    for (int i = 0; i < n && posi == -1; i++) {
        for (int j = 0; j < n && posi == -1; j++) {
            if (a[i][j] == 'Z') {
                posi = i, posj = j;
            }
        }
    }

    bfsDeath(posi, posj);

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (isdigit(a[i][j]) && a[i][j] != '0') {
                maxFlow.addEdge(S, i * n + j, a[i][j] - '0');
            }
        }
    }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (isdigit(b[i][j]) && b[i][j] != '0') {
                maxFlow.addEdge(i * n + j + sqr(n) + 1, T, b[i][j] - '0');
            }
        }
    }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (isdigit(a[i][j]) && a[i][j] != '0') {
                runBFS(i, j);
            }
        }
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in", "r", stdin);
#endif

    scanf("%d %d", &n, &t);

    scanf("\n");
    for (int i = 0; i < n; i++) {
        gets(a[i]);
    }

    scanf("\n");
    for (int i = 0; i < n; i++) {
        gets(b[i]);
    }

    build();

    printf("%d\n", maxFlow.getMaxFlow(S, T));

    return 0;
}