#include <bits/stdc++.h>

using namespace std;

typedef pair<int,int> par;

const int MAXR = 11;
const int MAXN = 1000;
const int MAXM = 100100;
const int oo = (1<<29);

int ady[2*MAXM], flow[2*MAXM], cap[2*MAXM], nxt[2*MAXM];
int last[MAXN], now[MAXN], lev[MAXN], cola[MAXN];
int E, n, s, t, enq, deq;

void init_maxflow( int nn, int ss, int tt ){
    n = nn; s = ss; t = tt; E = 2;
    for( int i = 0; i <= n; i++ ) last[i] = 0;

    //cerr << "n = " << n << "  s = " << s << "  t = " << t << '\n';
}
void add_edge( int u, int v, int c ){
    ady[E] = v; flow[E] = 0; cap[E] = c; nxt[E] = last[u]; last[u] = E++;
    ady[E] = u; flow[E] = 0; cap[E] = 0; nxt[E] = last[v]; last[v] = E++;

    //cerr << "u = " << u << "  -->  v = " << v << "  cap = " << c << '\n';
}
bool bfs(){
    for( int u = 0; u <= n; u++ ) lev[u] = 0;
    enq = deq = 0;
    cola[enq++] = s;
    lev[s] = 1;
    while( deq < enq && !lev[t] ){
        int u = cola[deq++];
        for( int e = last[u]; e; e = nxt[e] ){
            int v = ady[e];
            if( !lev[v] && flow[e] < cap[e] ){
                lev[v] = lev[u] + 1;
                cola[enq++] = v;
            }
        }
    }
    return lev[t];
}
int dfs( int u, int F ){
    if( u == t ) return F;
    for( int e = now[u], f = 0; e; e = now[u] = nxt[e] ){
        int v = ady[e];
        if( lev[u] < lev[v] && flow[e] < cap[e] &&
            (f = dfs( v , min( F , cap[e] - flow[e] ) )) ){
            flow[e] += f;
            flow[e^1] -= f;
            return f;
        }
    }
    return 0;
}
int max_flow(){
    int F = 0, f = 0;
    while( bfs() ){
        for( int i = 0; i <= n; i++ ) now[i] = last[i];
        while( (f = dfs( s , oo )) ) F += f;
    }
    return F;
}

int R;
string m1[MAXR];
string m2[MAXR];

int movI[] = { 0 , 1 , 0 , -1 };
int movJ[] = { 1 , 0 , -1 , 0 };

bool can_move( int i, int j ){
    return ( i >= 0 && j >= 0 && i < R && j < R && m1[i][j] != 'Y' && m1[i][j] != 'Z' );
}

int tim[2][MAXR][MAXR];

void bfs2( int i, int j, int cc ){
    for( int k = 0; k < R; k++ ){
        for( int l = 0; l < R; l++ ){
            tim[cc][k][l] = 0;
        }
    }

    tim[cc][i][j] = 1;
    queue<par> q;
    q.push( par( i , j ) );
    while( !q.empty() ){
        int i = q.front().first;
        int j = q.front().second;
        q.pop();

        if( cc == 1 && (tim[0][i][j] && tim[0][i][j] <= tim[1][i][j]) ){
            continue;
        }

        for( int k = 0; k < 4; k++ ){
            int ii = i + movI[k];
            int jj = j + movJ[k];

            if( can_move( ii , jj ) && !tim[cc][ii][jj] ){
                tim[cc][ii][jj] = tim[cc][i][j] + 1;
                q.push( par( ii , jj ) );
            }
        }
    }
}

int nod[2][MAXR][MAXR];

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    //freopen("dat.txt","r",stdin);

    int T; cin >> R >> T;

    int zi = 0, zj = 0;

    int n = 0, s = 0, t = 0;

    for( int i = 0; i < R; i++ ){
        cin >> m1[i];
        for( int j = 0; j < R; j++ ){
            if( m1[i][j] == 'Z' ){
                zi = i;
                zj = j;
            }
            else if( m1[i][j] != 'Y' ){
                n++;
                nod[0][i][j] = n;
            }
        }
    }

    for( int i = 0; i < R; i++ ){
        cin >> m2[i];
        for( int j = 0; j < R; j++ ){
            if( m2[i][j] != 'Y' && m2[i][j] != 'Z' ){
                n++;
                nod[1][i][j] = n;
            }
        }
    }

    n++;
    s = 0;
    t = n;

    init_maxflow( n , s , t );

    for( int i = 0; i < R; i++ ){
        for( int j = 0; j < R; j++ ){
            if( m1[i][j] != 'Z' && m1[i][j] != 'Y' ){
                add_edge( s , nod[0][i][j] , m1[i][j] - '0' );
                add_edge( nod[1][i][j] , t , m2[i][j] - '0' );
            }
        }
    }

    bfs2( zi , zj, 0 );

    //cerr << "T = " << T << '\n';

    for( int i = 0; i < R; i++ ){
        for( int j = 0; j < R; j++ ){
            if( m1[i][j] > '0' && m1[i][j] <= '9' ){
                bfs2( i , j , 1 );
                for( int ii = 0; ii < R; ii++ ){
                    for( int jj = 0; jj < R; jj++ ){
                        if( m2[ii][jj] > '0' && m2[ii][jj] <= '9' ){
                            if( tim[1][ii][jj] && (!tim[0][ii][jj] || tim[0][ii][jj] >= tim[1][ii][jj]) &&
                                tim[1][ii][jj]-1 <= T ){
                                add_edge( nod[0][i][j] , nod[1][ii][jj] , oo );
                                //cerr << "m1 = " << m1[i][j] << '\n';
                                //cerr << "i = " << i << " j = " << j << " ---> " << "ii = " << ii << " jj = " << jj << '\n';
                                //cerr << tim[1][ii][jj] << " - " << tim[0][ii][jj] << '\n';
                                //cerr << '\n';
                            }
                        }
                    }
                }
            }
        }
    }

    cout << max_flow() << '\n';
}


#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

int n, t;
struct pkt
{
    int x, y;
};

struct kraw
{
    int a, res;
};

int dx[] = {-1, 0, 1, 0, 0};
int dy[] = {0, 1, 0, -1, 0};

bool Ok(int x, int y)
{
    return (x >= 0 && x < n && y >= 0 && y < n);
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n >> t;
    vector<string> nau(n), pom(n);
    for (int i = 0; i < n; ++i)
        cin >> nau[i];
    for (int i = 0; i < n; ++i)
        cin >> pom[i];
    vector< vector<int> > odl(n, vector<int>(n, 1000));
    pkt start;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            if (nau[i][j] == 'Z')
                start = {i, j};
    queue<pkt> Q;
    odl[start.x][start.y] = 0;
    Q.push(start);
    while (!Q.empty())
    {
        pkt akt = Q.front();
        Q.pop();
        for (int i = 0; i < 4; ++i)
        {
            pkt nowy = {akt.x + dx[i], akt.y + dy[i]};
            if (Ok(nowy.x, nowy.y) && nau[nowy.x][nowy.y] >= '0' && nau[nowy.x][nowy.y] <= '9' && odl[nowy.x][nowy.y] == 1000)
            {
                odl[nowy.x][nowy.y] = odl[akt.x][akt.y] + 1;
                Q.push(nowy);
            }
        }
    }
    bool moge[60][10][10][10][10];
    for (int i = 0; i < 60; ++i)
        for (int j = 0; j < 10; ++j)
            for (int k = 0; k < 10; ++k)
                for (int l = 0; l < 10; ++l)
                    for (int m = 0; m < 10; ++m)
                        moge[i][j][k][l][m] = false;
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            for (int k = 0; k < 5; ++k)
            {
                int l = i + dx[k], m = j + dy[k];
                if (Ok(l, m) && nau[i][j] >= '0' && nau[i][j] <= '9' && nau[l][m] >= '0' && nau[l][m] <= '9')
                    moge[0][i][j][l][m] = true;
            }
        }
    }
    for (int i = 0; i <= t - 2; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            for (int k = 0; k < n; ++k)
            {
                for (int l = 0; l < n; ++l)
                {
                    for (int m = 0; m < n; ++m)
                    {
                        if (!moge[i][j][k][l][m])
                            continue;
                        for (int o = 0; o < 5; ++o)
                        {
                            int p = l + dx[o], r = m + dy[o];
                            if (Ok(p, r) && nau[p][r] >= '0' && nau[p][r] <= '9' && odl[l][m] >= i + 2 && odl[p][r] >= i + 2)
                                moge[i + 1][j][k][p][r] = true;
                        }
                    }
                }
            }
        }
    }
    vector<pkt> a;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            if (nau[i][j] >= '0' && nau[i][j] <= '9')
                a.push_back({i, j});
    int wie = 2 * a.size() + 2;
    vector< vector<kraw> > G(wie);
    for (int i = 0; i < a.size(); ++i)
    {
        G[0].push_back({i + 1, nau[a[i].x][a[i].y] - '0'});
        G[i + 1].push_back({0, 0});
        G[a.size() + 1 + i].push_back({wie - 1, pom[a[i].x][a[i].y] - '0'});
        G[wie - 1].push_back({a.size() + 1 + i, 0});
    }
    for (int i = 0; i < a.size(); ++i)
    {
        for (int j = 0; j < a.size(); ++j)
        {
            int ok = false;
            for (int k = 0; k <= t - 1; ++k)
                ok |= moge[k][a[i].x][a[i].y][a[j].x][a[j].y];
            if (ok)
            {
                G[i + 1].push_back({a.size() + 1 + j, 1000});
                G[a.size() + 1 + j].push_back({i + 1, 0});
            }
        }
    }
    int odp = 0;
    while (true)
    {
        vector<bool> odw(wie, false);
        queue<int> Q2;
        odw[0] = true;
        Q2.push(0);
        vector<int> pop(wie, -1);
        while (!Q2.empty())
        {
            int akt = Q2.front();
            Q2.pop();
            for (int i = 0; i < G[akt].size(); ++i)
            {
                if (!odw[G[akt][i].a] && G[akt][i].res > 0)
                {
                    Q2.push(G[akt][i].a);
                    pop[G[akt][i].a] = akt;
                    odw[G[akt][i].a] = true;
                }
            }
        }
        if (pop[wie - 1] == -1)
            break;
        vector<int> path;
        int akt = wie - 1;
        while (akt != -1)
        {
            path.push_back(akt);
            akt = pop[akt];
        }
        reverse(path.begin(), path.end());
        int flow = 1000;
        for (int i = 0; i < path.size() - 1; ++i)
            for (int j = 0; j < G[path[i]].size(); ++j)
                if (G[path[i]][j].a == path[i + 1])
                    flow = min(flow, G[path[i]][j].res);
        odp += flow;
        for (int i = 0; i < path.size() - 1; ++i)
            for (int j = 0; j < G[path[i]].size(); ++j)
                if (G[path[i]][j].a == path[i + 1])
                    G[path[i]][j].res -= flow;
        for (int i = 1; i < path.size(); ++i)
            for (int j = 0; j < G[path[i]].size(); ++j)
                if (G[path[i]][j].a == path[i - 1])
                    G[path[i]][j].res += flow;
    }
    cout << odp;
    return 0;
}


//lxrtxdy!
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define MAX_SIZE 7100
typedef long long ll;
#define INF 1000000000
using namespace std;

struct Maxflow {
    struct edge {
    	int from, to;
    	ll flow, capacity;
    };

    // start and end point
    int s, t;

    // list array
    vector<edge> edg;

    // g reference to the ith vertex's edges
    vector<int> g[MAX_SIZE];

    // distance array and visited array
    int dist[MAX_SIZE], visited[MAX_SIZE];
    int cur[MAX_SIZE];

    void init() {
    	edg.clear();
    	int i;
    	for (i = 0 ; i < MAX_SIZE; i++) {
    		g[i].clear();
    	}
    }

    void addedge(int from, int to, ll capacity) {
    	// cout << "addedge " << from << " " << to << " c= " << capacity << endl;
    	edge e1 = edge{from, to, 0ll, capacity};
    	edge e2 = edge{to, from, 0ll, 0ll};
    	edg.push_back(e1), edg.push_back(e2);
    	g[from].push_back((int) edg.size() - 2);
    	g[to].push_back((int) edg.size() - 1);
    }

    // construct the level graph
    bool bfs() {
    	memset(visited,0,sizeof(visited));
    	memset(dist,0,sizeof(dist));
    	queue<int> q;
    	q.push(s);
    	visited[s] = 1;
    	dist[s] = 0;
    	while (!q.empty()) {
    		int v = q.front();
    		q.pop();
    		for (int i = 0 ; i < (int) g[v].size(); i++) {
    			edge &e = edg[g[v][i]];
    			int nxt = e.to;
    			if (!visited[nxt] && e.capacity > e.flow) {
    				dist[nxt] = dist[v] + 1;
    				q.push(nxt);
    				visited[nxt] = 1;
    			}
    		}
    	}

    	return visited[t];
    }

    ll dfs(int x, ll cp) {
    	if (x == t || cp == 0) {
    		return cp;
    	}

    	ll flow = 0, newflow;
    	for (int &y = cur[x]; y < (int) g[x].size(); y++) {
    		edge &e = edg[g[x][y]];
    		if (dist[x] + 1 == dist[e.to]) {
    			ll minn = min(cp, e.capacity - e.flow);
    			newflow = dfs(e.to, minn);
    			if (newflow > 0) {
    				e.flow += newflow;
    				edg[g[x][y] ^1].flow -= newflow;
    				flow += newflow;
    				cp -= newflow;

    				if (cp == 0) {
    					break;
    				}
    			}
    		}
    	}

    	return flow;
    }

    ll Dinic(){
        ll flow=0;
        while(bfs()){
            memset(cur,0,sizeof(cur));
            flow += dfs(s,INF);
        }
        return flow;
    }
};

Maxflow mf;
char g1[14][14];
char g2[14][14];
bool visited[14][14];
int dist[14][14];
int n;
int tgt[103];

void BFS(int x, int y) {
	queue<pair<pair<int, int>, int> > q;
	int i, j;
	for (i = 0 ; i < 14; i++) {
		for (j = 0 ; j < 14; j++) {
			dist[i][j] = 111;
		}
	}

	dist[x][y] = 0;
	q.push(make_pair(make_pair(x, y), 0));
	int dx[4] = {1, 0, 0, -1}, dy[4] = {0, 1, -1, 0};
	while (!q.empty()) {
        auto p = q.front();
        q.pop();
        if (visited[p.first.first][p.first.second]) continue;
        visited[p.first.first][p.first.second] = true;
        dist[p.first.first][p.first.second] = p.second;
        for (i = 0; i < 4; i++) {
			int tx = dx[i] + p.first.first, ty = dy[i] + p.first.second;
			if (tx <= 0 || tx > n || ty <= 0 || ty > n
			    || visited[tx][ty] || g1[tx][ty] == 'Y') continue;
			q.push(make_pair(make_pair(tx, ty), p.second + 1));
		}
	}
}

int index(int level, int x, int y) {
	return level * n * n + (x - 1) * n + y;
}

int main() {
	int i, t, j, k;
	scanf("%d%d", &n, &t);
	for (i = 1; i <= n; i++) scanf("%s", g1[i] + 1);
	for (i = 1; i <= n; i++) scanf("%s", g2[i] + 1);

	mf.s = 0, mf.t = MAX_SIZE - 2;
	int x = 0, y = 0;
	for (i = 1; i <= n; i++) {
		for (j = 1; j <= n; j++) {
			if (g1[i][j] == 'Z') {
			   x = i, y = j;
			   break;
			}
		}
	}

	for (i = 1; i <= n * n; i++) tgt[i] = MAX_SIZE - 3 - (n * n - i);

	BFS(x, y);

	for (i = 1; i <= n; i++) {
		for (j = 1; j <= n; j++) {
			if (g1[i][j] >= '0' && g1[i][j] <= '9')
		        mf.addedge(mf.s, index(0, i, j), g1[i][j] - '0');

			if (g2[i][j] >= '0' && g2[i][j] <= '9')
			    mf.addedge(tgt[index(0, i, j)], mf.t, g2[i][j] - '0');
			mf.addedge(index(0, i, j), tgt[index(0, i, j)], INF);
		}
	}

	int dx[4] = {1, 0, 0, -1}, dy[4] = {0, 1, -1, 0};
	for (i = 1; i <= t; i++) {
		for (j = 1; j <= n; j++) {
			for (k = 1; k <= n; k++) {
				if (g1[j][k] == 'Y' || g1[j][k] == 'Z') continue;
				for (int l = 0 ; l < 4; l++) {
					int tx = dx[l] + j, ty = dy[l] + k;
					if (tx >= 1 && tx <= n && ty >= 1 && ty <= n && g1[tx][ty] != 'Y' && g1[tx][ty] != 'Z') {
					   if (dist[j][k] >= i && dist[tx][ty] >= i && g1[j][k] != 'Y' && g1[j][k] != 'Z') {
					   	  mf.addedge(index(i-1, tx, ty), index(i, j, k), INF);
					   }
					}
				}

				mf.addedge(index(i, j, k), tgt[index(0, j, k)], INF);
			}
		}
	}
	printf("%lld\n", mf.Dinic());
	return 0;
}
//orzlxr!//hello


//C - Evacuation:
//Assunto: Flow;
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define loop(i, a, b) for(int i = a; i < b; i++)
#define loopBack(i, a, b) for(int i = a; i >= b; i--)
#define INF INT_MAX
#define LINF LLONG_MAX
#define DINF DBL_MAX
#define MAX 150
#define MOD 1000
using namespace std;
typedef long long int ll;
typedef pair<int, int> ii;

struct FlowEdge {
    int v, u;
    ll cap, flow = 0;
    FlowEdge(int v, int u, ll cap) : v(v), u(u), cap(cap) {}
};

struct Dinic {
    const ll flow_inf = 1e18;
    vector<FlowEdge> edges;
    vector<vector<int>> adj;
    int n, m = 0;
    int s, t;
    vector<int> level, ptr;
    queue<int> q;

    Dinic(int n, int s, int t) : n(n), s(s), t(t) {
        adj.resize(n);
        level.resize(n);
        ptr.resize(n);
    }

    void add(int v, int u, ll cap) {
        edges.emplace_back(v, u, cap);
        edges.emplace_back(u, v, 0);
        adj[v].push_back(m);
        adj[u].push_back(m+1);
        m += 2;
    }

    bool bfs() {
        while(!q.empty()) {
            int v = q.front();
            q.pop();
            for(int viz : adj[v]) {
                if(edges[viz].cap - edges[viz].flow < 1) continue;
                if(level[edges[viz].u] != -1) continue;
                level[edges[viz].u] = level[v] + 1;
                q.push(edges[viz].u);
            }
        }
        return level[t] != -1;
    }

    ll dfs(int v, ll pushed) {
        if(pushed == 0) return 0;
        if(v == t) return pushed;
        for(int &i = ptr[v]; i < (int)adj[v].size(); i++) {
            int viz = adj[v][i];
            int u = edges[viz].u;
            if(level[v] + 1 != level[u] || edges[viz].cap - edges[viz].flow < 1) continue;
            ll tr = dfs(u, min(pushed, edges[viz].cap - edges[viz].flow));
            if(tr == 0) continue;

            edges[viz].flow += tr;
            edges[viz ^ 1].flow -= tr;
            return tr;
        }
        return 0;
    }

    ll flow() {
        ll f = 0;
        while(true) {
            fill(all(level), -1);
            level[s] = 0;
            q.push(s);
            if(!bfs()) break;
            fill(all(ptr), 0);
            while(ll pushed = dfs(s, flow_inf))
                f += pushed;
        }
        return f;
    }
};

int pos[MAX][MAX], matTempo[MAX][MAX], matAlc[MAX][MAX];

vector<ii> pegaVizinhos(int i, int j, vector<string> mat, int n) {
    vector<ii> viz;
    if(i + 1 < n) viz.pb({i+1, j});
    if(i - 1 >= 0) viz.pb({i-1, j});
    if(j + 1 < n) viz.pb({i, j+1});
    if(j - 1 >= 0) viz.pb({i, j-1});
    return viz;
}

void criaMatTempo(int i, int j, vector<string> sc, int n, int currT) {
    if(i >= n || i < 0 || j >= n || j < 0 || (!isdigit(sc[i][j]) && sc[i][j] != 'Z') || (matTempo[i][j] != -1 and matTempo[i][j] <= currT)) return;
    if(matTempo[i][j] == -1)
        matTempo[i][j] = currT;
    else
        matTempo[i][j] = min(currT, matTempo[i][j]);
    criaMatTempo(i+1, j, sc, n, currT+1);
    criaMatTempo(i-1, j, sc, n, currT+1);
    criaMatTempo(i, j+1, sc, n, currT+1);
    criaMatTempo(i, j-1, sc, n, currT+1);
}

void criaMatAlc(int i, int j, vector<string> sc, int n, int currT) {
    if(i >= n || i < 0 || j >= n || j < 0 || (matAlc[i][j] != -1 and matAlc[i][j] <= currT) || !isdigit(sc[i][j])) return;
    if(matAlc[i][j] == -1)
        matAlc[i][j] = currT;
    else
        matAlc[i][j] = min(currT, matAlc[i][j]);
    criaMatAlc(i+1, j, sc, n, currT+1);
    criaMatAlc(i-1, j, sc, n, currT+1);
    criaMatAlc(i, j+1, sc, n, currT+1);
    criaMatAlc(i, j-1, sc, n, currT+1);
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    // freopen("in.txt", "r", stdin);
    int n, t, n2, nMax, iZ, jZ;
    string aux;

    cin >> n >> t;
    n2 = n * n;
    nMax = n2 * 2;
    Dinic grafo = Dinic(nMax + 2, 0, nMax + 1);
    vector<string> sc(n), caps(n);

    //Calcular Posicao
    int cnt = 1;
    loop(i, 0, n) {
        loop(j, 0, n) {
            pos[i][j] = cnt;
            cnt++;
        }
    }

    loop(i, 0, n) {
        cin >> sc[i];
        loop(j, 0, n) {
            if(sc[i][j] == 'Z') {
                iZ = i;
                jZ = j;
            }
        }
    }
    loop(i, 0, n) cin >> caps[i];

    memset(matTempo, -1, sizeof(matTempo));
    criaMatTempo(iZ, jZ, sc, n, 0);
    loop(i, 0, n) {
        loop(j, 0, n) {
            if(matTempo[i][j] == -1 and isdigit(sc[i][j])) matTempo[i][j] = t;
        }
    }

    loop(i, 0, n) {
        loop(j, 0, n) {
            memset(matAlc, -1, sizeof(matAlc));
            if(isdigit(sc[i][j])) {
                int lmt = sc[i][j] - '0';
                grafo.add(0, pos[i][j], lmt);
                criaMatAlc(i, j, sc, n, 0);
                loop(k, 0, n) {
                    loop(l, 0, n) {
                        if(matAlc[k][l] != -1 and matTempo[k][l] != -1 and matAlc[k][l] <= matTempo[k][l] and matAlc[k][l] <= t) {
                            bool crt = true;
                            if(matAlc[k][l] == matTempo[k][l]) {
                                crt = false;
                                if(k+1 < n and matAlc[k+1][l] != -1 and matAlc[k+1][l] < matTempo[k+1][l]) crt = true;
                                if(k-1 >= 0 and matAlc[k-1][l] != -1 and matAlc[k-1][l] < matTempo[k-1][l]) crt = true;
                                if(l+1 < n and matAlc[k][l+1] != -1 and matAlc[k][l+1] < matTempo[k][l+1]) crt = true;
                                if(l-1 >= 0 and matAlc[k][l-1] != -1 and matAlc[k][l-1] < matTempo[k][l-1]) crt = true;
                            }
                            if(crt) {
                                grafo.add(pos[i][j], n2+pos[k][l], lmt);
                            }
                        }
                    }
                }
            }
        }
    }

    loop(i, 0, n) {
        loop(j, 0, n) {
            if(isdigit(caps[i][j])) {
                grafo.add(n2+pos[i][j], nMax+1, caps[i][j] - '0');
            }
        }
    }

    ll ans = grafo.flow();
    cout << ans << '\n';
}


/*
 *  Problema:
 *  Tecnica Utilizada:
 *
 *
 *  Dificuldade:
 *	Complexidade:
 *				O(  )
 */

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <ctime>
#include <cfloat>
#include <vector>
#include <string>
#include <cstdio>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>

#define INF 10*10*10
#define LINF 0x3F3F3F3FFFFFFFFF

#define FOR(i, a, b) for(int i = a; i < b; ++i)
#define RFOR(i, b, a) for(int i = b - 1; i >= a; --i)
#define REP(i, N) FOR(i, 0, N)
#define RREP(i, N) RFOR(i, N, 0)
#define FORIT(i, a) for( TI(a) i = a.begin(); i != a.end(); i++ )

#define FILL(X, V) memset( X, V, sizeof(X) )
#define TI(X) typeof(X.begin())
#define ALL(V) V.begin(), V.end()
#define SIZE(V) (int)V.size()

#define pb push_back
#define mp make_pair

template<typename T> T inline SQR( const T &a ){ return a*a; }
template<typename T> T inline ABS( const T &a ){ return a < 0 ? -a : a; }
template<typename T> T inline MIN( const T& a, const T& b){ if( a < b ) return a; return b; }
template<typename T> T inline MAX( const T& a, const T& b){ if( a > b ) return a; return b; }

typedef long long int64;
typedef unsigned long long uint64;

using namespace std;

int N, M;
int cap[2002][2002];
vector< int > gr[2002];
bool vis[2002];
int parent[2002];

int ds[][2] = { {1,0}, {0,1}, {-1,0}, {0,-1} };

int augment( int u ){

	if( u == 1 ) return INF;
	vis[u] = true;

	REP( i, SIZE(gr[u]) ) if( !vis[gr[u][i]] && cap[u][gr[u][i]] ){
		int r = augment( gr[u][i] );
		if( r ){
			parent[ gr[u][i] ] = u;
			return MIN( r, cap[u][ gr[u][i] ] );
		}
	}

	return 0;

}

int maxflow(){
	int ans = 0;
	int flow = 0;

	parent[0] = -1;
	do{
		ans += flow;

		REP( i, M ) vis[i] = false;
		flow = augment(0);

		if (!flow) return ans;

		int v = 1;
		while( v != 0 ){
			int u = parent[v];
			cap[u][v] -= flow;
			cap[v][u] += flow;
			v = u;
		}
	} while( flow );

	return ans;
}

int main( int argc, char* argv[] ){

	ios::sync_with_stdio( false );

	int dim, time_to_die;
	cin >> dim >> time_to_die;

	REP( i, 2*dim*dim + 2 ){
		gr[i].clear();
		REP( j, 2*dim*dim + 2 ) cap[i][j] = 0;
	}
	vector< string > labsci(dim), labcap(dim);

	int vert[dim][dim][2];
	int malfunc;

	N = 2;
	REP( i, dim ){
		cin >> labsci[i];
		REP( j, dim ) if( labsci[i][j] <= '9' && labsci[i][j] >= '1' ){
			cap[0][N] = labsci[i][j]-'0';
			gr[0].pb( N );
			gr[N].pb( 0 );
			vert[i][j][0] = N++;
		} else if( labsci[i][j] == 'Z' ) { malfunc = 100*i + j; labsci[i][j] = 'Y'; }
	}

	M = N;
	REP( i, dim ){
		cin >> labcap[i];
		REP( j, dim ) if( labcap[i][j] <= '9' && labcap[i][j] >= '1' ){
			cap[M][1] = labcap[i][j]-'0';
			gr[M].pb( 1 );
			vert[i][j][1] = M++;
		}
	}

	int die[dim][dim];
	REP( i, dim ) REP( j, dim ) die[i][j] = time_to_die+1;
	die[ malfunc/100 ][ malfunc%100 ] = 0;

	queue< int > q;
	q.push( malfunc );
	int x, y, nx, ny;
	while( !q.empty() ){
		x = q.front(); q.pop();
		y = x%100; x /= 100;

		REP( i, 4 ){
			nx = x+ds[i][0];
			ny = y+ds[i][1];
			if( nx >= 0 && nx < dim && ny >= 0 && ny < dim && labsci[nx][ny] != 'Y' && die[nx][ny] > die[x][y]+1 ){
				die[nx][ny] = die[x][y]+1;
				q.push( 100*nx + ny );
			}
		}
	}

	int reach[dim][dim];
	REP( i, dim ) REP( j, dim ) if( labsci[i][j] <= '9' && labsci[i][j] >= '1' ){

		REP( ii, dim ) REP( jj, dim ) reach[ii][jj] = time_to_die+1;
		reach[i][j] = 0;

		if( labcap[i][j] <= '9' && labcap[i][j] >= '1' ){
			cap[ vert[i][j][0] ][ vert[i][j][1] ] = INF;
			gr[ vert[i][j][0] ].pb( vert[i][j][1] );
			gr[ vert[i][j][1] ].pb( vert[i][j][0] );
		}

		q.push( 100*i + j );
		while( !q.empty() ){
			x = q.front(); q.pop();
			y = x%100; x/= 100;

			REP( dd, 4 ){
				nx = x+ds[dd][0];
				ny = y+ds[dd][1];
				if( nx >= 0 && nx < dim && ny >= 0 && ny < dim && labsci[nx][ny] != 'Y' && reach[nx][ny] > reach[x][y]+1 ){
					if( labcap[nx][ny] <= '9' && labcap[nx][ny] >= '1' ){
						if( reach[x][y]+1 <= die[nx][ny] ){
							cap[ vert[i][j][0] ][ vert[nx][ny][1] ] = INF;
							gr[ vert[i][j][0] ].pb( vert[nx][ny][1] );
							gr[ vert[nx][ny][1] ].pb( vert[i][j][0] );
						}
					}
					if( reach[x][y]+1 < die[nx][ny] ){
						reach[nx][ny] = reach[x][y]+1;
						q.push( 100*nx + ny );
					}
				}
			}
		}
	}

	cout << maxflow() << endl;

	return 0;
}


#include<stdio.h>
#include<string.h>
#define inf 0x1fffffff
#define MAXN 210
int Min(int x,int y)
{
    if(x<y)
        return x;
    else
        return y;
}
struct Edge
{
    int u,v,next,s;
}edge[4000000];
int head[MAXN];
int cur[MAXN];
int pos;
void insert(int x,int y,int s)
{
    edge[pos].u=x;
    edge[pos].v=y;
    edge[pos].s=s;
    edge[pos].next=head[x];
    head[x]=pos++;
}
int queue[MAXN];
int dis[MAXN];
bool bfs(int nodenum,int src,int tc)
{
    int i;
    int v,s;
    int now;
    int front,rear;
    front=rear=0;
    queue[rear++]=src;
    memset(dis,-1,sizeof(dis));
    dis[src]=0;
    while(front<rear)
    {
        now=queue[front++];
        for(i=head[now];i!=-1;i=edge[i].next)
        {
            now=edge[i].u;
            v=edge[i].v;
            s=edge[i].s;
            if(s>0 && dis[v] == -1)    //s > eps
            {
                dis[v]=dis[now]+1;
                queue[rear++]=v;
                if(v == tc)
                    return true;
            }
        }
    }
    return false;
}
int dinic(int nodenum,int src,int tc)
{
    int u,v,s;
    int max_flow=0;
    int i;
    int temp;
    int now;
    int rear;
    int hh;
    while(bfs(nodenum,src,tc))
    {
        now=src;
        rear=0;
        for(i=0;i<=nodenum;i++)//记得全部要复制
            cur[i]=head[i];
        while(cur[src]!=-1)
        {
            hh=cur[now];
            u=edge[hh].u;
            v=edge[hh].v;
            s=edge[hh].s;
            if(now!=tc && hh!=-1 && s>0 && dis[now]!=-1 && dis[now]+1==dis[v])    //s > eps
            {
                queue[rear++]=hh;
                now=v;
            }
            else if(now == tc)
            {
                temp=inf;
                for(i=rear-1;i>=0;i--)
                    temp=Min(temp,edge[queue[i]].s);
                max_flow+=temp;
                for(i=rear-1;i>=0;i--)
                {
                    edge[queue[i]].s-=temp;
                    edge[queue[i]^1].s+=temp;
                    if(edge[queue[i]].s == 0)    // fabs(edge[queue[i]].s) < eps
                        rear=i;
                }
                now=edge[queue[rear]].u;
            }
            else
            {
                while(rear>0 && now!=src && cur[now]==-1)
                    now=edge[queue[--rear]].u;
                cur[now]=edge[cur[now]].next;
            }
        }
    }
    return max_flow;
}
char graph1[20][20];
char graph2[20][20];
int mark[20][20];
int mark1[20][20];
int mark2[20][20];
int n,limit;
int ss,tt;
int id;
void bfs1(int pos,int num)
{
    if(mark[pos/n][pos%n] != 0)
    {
        insert(id,-mark[pos/n][pos%n],inf);
        insert(-mark[pos/n][pos%n],id,0);
    }
    int rear,front;
    int ax[4]={0,1,0,-1};
    int ay[4]={1,0,-1,0};
    rear=front=0;
    queue[front++]=pos;
    memset(mark1,-1,sizeof(mark1));
    mark1[pos/n][pos%n]=0;
    //for(int i=0;i<n;i++)
    //  printf("%s\n",graph1[i]);
    while(rear != front)
    {
        int now=queue[rear++];
        int x,y;
        x=now/n;
        y=now%n;
        int xx,yy;
        for(int i=0;i<4;i++)
        {
            xx=x+ax[i];
            yy=y+ay[i];
            if(xx < 0 || xx >= n || yy < 0 || yy >=n)
                continue;
            if(graph2[xx][yy] == 'Y' || graph2[xx][yy] == 'Z')
                continue;
            if(mark[xx][yy] != 0 && mark1[xx][yy] == -1)
            {
                if(mark2[xx][yy] == -1 || mark2[xx][yy] >= mark1[x][y] + 1)
                {
                    insert(id,-mark[xx][yy],inf);
                    insert(-mark[xx][yy],id,0);
                }
            }
            if((mark2[xx][yy] == -1 || mark2[xx][yy] > mark1[x][y] + 1) && mark1[xx][yy] == -1)
            {
                mark1[xx][yy]=mark1[x][y]+1;
                if(mark1[xx][yy] < limit)
                    queue[front++]=xx*n+yy;
            }
        }
    }
    insert(ss,id,num);
    insert(id,ss,0);
    //printf("---%d %d\n",pos/n,pos%n);
    id++;
    //for(int i=0;i<n;i++)
    //  printf("%s\n",graph1[i]);
}
void bfs2()
{
    int rear,front;
    rear=front=0;
    memset(mark,0,sizeof(mark));
    memset(mark2,-1,sizeof(mark2));
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            if(graph2[i][j] == 'Z')
            {
                queue[front++]=i*n+j;
                mark2[i][j]=0;
            }
            if(graph2[i][j] >= '1' && graph2[i][j] <= '9')
            {
                insert(id,tt,graph2[i][j]-'0');
                insert(tt,id,0);
                mark[i][j]=-id;
                id++;
            }
        }
    int ax[4]={0,1,0,-1};
    int ay[4]={1,0,-1,0};
    while(rear != front)
    {
        int now=queue[rear++];
        int x,y;
        x=now/n;
        y=now%n;
        int xx,yy;
        for(int i=0;i<4;i++)
        {
            xx=x+ax[i];
            yy=y+ay[i];
            if(xx < 0 || xx >= n || yy < 0 || yy >=n)
                continue;
            if(graph2[xx][yy] == 'Y' || graph2[xx][yy] == 'Z')
                continue;
            if(mark2[xx][yy] == -1)
            {
                mark2[xx][yy]=mark2[x][y]+1;
                if(mark2[xx][yy] < limit)
                    queue[front++]=xx*n+yy;
            }
        }
    }
    /*for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
            printf("%d ",mark[i][j]);
        printf("\n");
    }*/
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            if(graph1[i][j] >= '1' && graph1[i][j] <= '9')
                bfs1(i*n+j,graph1[i][j]-'0');
        }
    int ans=dinic(id-1,ss,tt);
    printf("%d\n",ans);
    //for(int i=0;i<pos;i+=2)
    //  printf("%d %d %d\n",edge[i].u,edge[i].v,edge[i].s);
}
int main()
{
    char fuck[10000];
    scanf("%d %d",&n,&limit);
    gets(fuck);
    for(int i=0;i<n;i++)
        gets(graph1[i]);
    gets(fuck);
    for(int i=0;i<n;i++)
        gets(graph2[i]);
    memset(head,-1,sizeof(head));
    pos=0;
    id=0;
    ss=id++;//src=0;
    tt=id++;//tc=1;
    bfs2();
    //printf("%d\n",id);
    return 0;
}


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

#define FAST ios_base::sync_with_stdio(false);cin.tie(NULL);
#define endl '\n'

typedef long long ll;
typedef pair<int,int> pii;
/*
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>
using namespace __gnu_pbds;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ost; // set
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> indexed_multiset; // multiset
*/

// Bitmask

/*
bool check(int mask,int pos){return mask&(1<<pos);}
int SET(int mask,int pos){return mask|(1<<pos);}
int FLIP(int mask,int pos){return mask^(1<<pos);}
*/

//4 direction
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};

struct FlowEdge {
    int v, u;
    long long cap, flow = 0;
    FlowEdge(int v, int u, long long cap) : v(v), u(u), cap(cap) {}
};

struct Dinic {
    const long long flow_inf = 1e18;
    vector<FlowEdge> edges;
    vector<vector<int>> adj;
    int n, m = 0;
    int s, t;
    vector<int> level, ptr;
    queue<int> q;

    Dinic(int n, int s, int t) : n(n), s(s), t(t) {
        adj.resize(n);
        level.resize(n);
        ptr.resize(n);
    }

    void add_edge(int v, int u, long long cap) {
        edges.emplace_back(v, u, cap);
        edges.emplace_back(u, v, 0);
        adj[v].push_back(m);
        adj[u].push_back(m + 1);
        m += 2;
    }

    bool bfs() {
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            for (int id : adj[v]) {
                if (edges[id].cap - edges[id].flow < 1)
                    continue;
                if (level[edges[id].u] != -1)
                    continue;
                level[edges[id].u] = level[v] + 1;
                q.push(edges[id].u);
            }
        }
        return level[t] != -1;
    }

    long long dfs(int v, long long pushed) {
        if (pushed == 0)
            return 0;
        if (v == t)
            return pushed;
        for (int& cid = ptr[v]; cid < (int)adj[v].size(); cid++) {
            int id = adj[v][cid];
            int u = edges[id].u;
            if (level[v] + 1 != level[u] || edges[id].cap - edges[id].flow < 1)
                continue;
            long long tr = dfs(u, min(pushed, edges[id].cap - edges[id].flow));
            if (tr == 0)
                continue;
            edges[id].flow += tr;
            edges[id ^ 1].flow -= tr;
            return tr;
        }
        return 0;
    }

    long long flow() {
        long long f = 0;
        while (true) {
            fill(level.begin(), level.end(), -1);
            level[s] = 0;
            q.push(s);
            if (!bfs())
                break;
            fill(ptr.begin(), ptr.end(), 0);
            while (long long pushed = dfs(s, flow_inf)) {
                f += pushed;
            }
        }
        return f;
    }
};

int n,t;
string sci[15];
string cap[15];
int dis[15][15];
int dis2[15][15];

bool isvalid(int x,int y)
{
    if(x<0 || y<0 || x>=n || y>=n) return false;
    if(sci[x][y]=='Y' || sci[x][y]=='Z') return false;
    return true;
}

void bfs1(int x,int y)
{
    queue<pii>q;
    q.push({x,y});
    memset(dis,-1,sizeof dis);
    dis[x][y]=0;
    while(!q.empty()){
        pii u=q.front();
        q.pop();
        for(int i=0;i<4;i++){
            int vx=u.first+dx[i];
            int vy=u.second+dy[i];
            if(isvalid(vx,vy) && dis[vx][vy]==-1){
                dis[vx][vy]=1+dis[u.first][u.second];
                q.push({vx,vy});
            }
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(dis[i][j]==-1)
                dis[i][j]=1000000000;
        }
    }
}

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

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

    if(tt>=t) return 0;

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

    if(dp[tt][x0][y0][x][y]!=-1) return dp[tt][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(sci[xx][yy]=='Y') continue;
        if(sci[xx][yy]=='Z') continue;

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

int main()
{
    memset(dp,-1,sizeof dp);
    cin>>n>>t;
    for(int i=0;i<n;i++){
        cin>>sci[i];
    }
    for(int i=0;i<n;i++){
        cin>>cap[i];
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(sci[i][j]=='Z'){
                bfs1(i,j);
                break;
            }
        }
    }
    vector<pii>sc,cp;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(sci[i][j]!='Z' && sci[i][j]!='Y' && sci[i][j]!='0'){
                sc.push_back({i,j});
            }
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(cap[i][j]!='Z' && cap[i][j]!='Y' && cap[i][j]!='0'){
                cp.push_back({i,j});
            }
        }
    }

    Dinic flow(sc.size()+cp.size()+2,0,sc.size()+cp.size()+1);
    for(int i=0;i<sc.size();i++){
        ll c=sci[sc[i].first][sc[i].second]-'0';
        flow.add_edge(0,i+1,c);
    }
    for(int i=0;i<cp.size();i++){
        ll c=cap[cp[i].first][cp[i].second]-'0';
        flow.add_edge(sc.size()+1+i,sc.size()+cp.size()+1,c);
    }

    for(int i=0;i<sc.size();i++){
        for(int j=0;j<cp.size();j++){
            if(pos(0,sc[i].first,sc[i].second,cp[j].first,cp[j].second)){
                flow.add_edge(i+1,sc.size()+1+j,10000000);
            }
        }
    }
    cout<<flow.flow()<<endl;
}


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

const int MAXN = 300;
const int INF = 1e9;

struct edge{
    int to, rev, f, cap;
    edge(int to, int rev, int f, int cap) : to(to), rev(rev), f(f), cap(cap) {}
};
vector<edge> adj[MAXN];

void add_edge(int u, int v, int c, int rc = 0) {
    edge a(v, adj[v].size(), 0, c);
    edge b(u, adj[u].size(), 0, rc);
    adj[u].push_back(a);
    adj[v].push_back(b);
}

int dis[MAXN], ptr[MAXN], src, dst;

bool bfs() {
    memset(dis, -1, sizeof dis);
    dis[src] = 0;
    queue<int> q({src});
    while(q.size() && dis[dst] == -1) {
        int u = q.front(); q.pop();
        for(auto e : adj[u]) {
            int v = e.to;
            if(dis[v]==-1 && e.f < e.cap) {
                dis[v] = dis[u] + 1;
                q.push(v);
            }
        }
    }
    return dis[dst] != -1;
}

int dfs(int u, int f) {
    if(u == dst || !f)
           return f;
    for(int &i = ptr[u]; i < adj[u].size(); i++){
        edge &e = adj[u][i];
        int v = e.to;
        if(dis[v] != dis[u] + 1)
                continue;
        if(int df = dfs(v, min(f, e.cap - e.f))) {
            e.f += df;
            adj[v][e.rev].f -= df;
            return df;
        }
    }
    return 0;
}

int mf() {
    int res = 0;
    while(bfs()) {
        memset(ptr, 0, sizeof ptr);
        while(int df = dfs(src, INF))
            res += df;
    }
    return res;
}

int dx[] = {-1, 0, 0, 1};
int dy[] = {0, -1, 1, 0};

int n, m;
typedef vector<vector<int>> grid;
typedef array<int, 2> pa;
grid obs, tim, dii;

void gbfs(int r, int c, grid &dis, bool chk = false) {
    for(int i = 0; i < n; i++)
        fill(dis[i].begin(), dis[i].end(), -1);
    dis[r][c] = 0;
    queue<pa> q;
    q.push({r, c});
    while(q.size()) {
        auto p = q.front(); q.pop();
        if(chk && dis[p[0]][p[1]] == tim[p[0]][p[1]])
        	continue;
        pa r;
        for(int i = 0; i < 4; i++) {
            r = {p[0] + dx[i], p[1] + dy[i]};
            if(r[0] < 0 || r[0] >= n || r[1] < 0 || r[1] >= n || dis[r[0]][r[1]] != -1 || obs[r[0]][r[1]])
                continue;
            if(chk && tim[r[0]][r[1]] > -1 && dis[p[0]][p[1]] + 1 > tim[r[0]][r[1]])
            	continue;
            dis[r[0]][r[1]] = dis[p[0]][p[1]] + 1;
            q.push(r);
        }
    }
}

vector<string> lab, rea;

int main() {
    cin >> n >> m;
    lab.resize(n);
    rea.resize(n);
    for(auto &x : lab)
        cin >> x;
    for(auto &x : rea)
        cin >> x;
    obs.assign(n, vector<int>(n));
    tim.assign(n, vector<int>(n));
    dii.assign(n, vector<int>(n));
    for(int i = 0; i < n; i++)
    	for(int j = 0; j < n; j++)
    		obs[i][j] = (lab[i][j] == 'Y');
    for(int i = 0; i < n; i++)
    	for(int j = 0; j < n; j++)
    		if(lab[i][j] == 'Z')
    			gbfs(i, j, tim);
    src = 2*n*n + 5;
    dst = src + 1;
    for(int x = 0; x < n; x++) {
    	for(int y = 0; y < n; y++) {
    		if(lab[x][y] == 'Z' || lab[x][y] == 'Y')
    			continue;
    		add_edge(src, n*x + y, lab[x][y] - '0');
    		add_edge(n*n + n*x + y, dst, rea[x][y] - '0');
    		gbfs(x, y, dii, true);
    		for(int xp = 0; xp < n; xp++) {
    			for(int yp = 0; yp < n; yp++) {
    				if(dii[xp][yp] != -1 && dii[xp][yp] <= m) {
    					add_edge(n*x + y, n*n + n*xp + yp, INF);
    				}
    			}
    		}
    	}
    }
    cout << mf() << '\n';
}


#include <iostream>
#include <queue>
#include <map>
using namespace std;
typedef map<int,int> mi;

mi edge[7000];
char buf[20][20];
int n,m,vn,from[7000],flow[7000],tox[10][10];

inline int aug(int s,int t,int cap){
  int result=0;
  for (int aug=1; aug--;){
    for (int i=vn; i--;) from[i]=-1;
    from[s]=s;
    flow[s]=cap;
    queue<int> bfs;
    for (bfs.push(s); not bfs.empty(); bfs.pop()){
      int x=bfs.front();
      if (x==t){
        for (aug=1; x!=s; x=from[x])
          edge[from[x]][x]-=flow[t],
          edge[x][from[x]]+=flow[t];
        result+=flow[t];
        break;
      }
      for (mi::iterator e=edge[x].begin(); e!=edge[x].end(); e++)
        if (e->second>=cap and !~from[e->first])
          from[e->first]=x, flow[e->first]=min(e->second,flow[x]), bfs.push(e->first);
    }
  }
  return result;
}

inline int enc(int x,int y,int t){
  return x+y*n+t*n*n+2;
}

int main(){
  ios::sync_with_stdio(0);
  cin>>n>>m;

  int res=0;
  for (int i=0; i<n; i++)
    for (int j=!(cin>>buf[i]); j<n; j++)
      if (buf[i][j]>'0' and buf[i][j]<='9') edge[0][enc(i,j,0)]=buf[i][j]-'0';
  for (int i=0; i<n; i++) cin>>buf[i];

  static int const dx[]={-1,0,1,0};
  static int const dy[]={0,-1,0,1};

  queue<pair<int,int>> bfs;
  for (int i=n; i--;)
    for (int j=n; j--;){
      if (buf[i][j]=='Z') tox[i][j]=0, bfs.emplace(i,j);
      else tox[i][j]=m+1;
    }

  for (; not bfs.empty(); bfs.pop()){
    for (int i=4; i--;){
      int t=tox[bfs.front().first][bfs.front().second];
      int x=bfs.front().first+dx[i];
      int y=bfs.front().second+dy[i];
      if (x>=0 and y>=0 and x<n and y<n and buf[x][y]!='Y' and t+1<tox[x][y]){
        tox[x][y]=t+1;
        bfs.emplace(x,y);
      }
    }
  }

  vn=enc(n-1,n-1,m)+1;

  for (int i=n; i--;)
    for (int j=n; j--;){
      for (int t=0; t<m; t++){
        if (t<m) for (int q=4; q--;){
          int x=i+dx[q];
          int y=j+dy[q];
          if (x>=0 and y>=0 and x<n and y<n and buf[x][y]!='Y' and t+1<tox[x][y]+(buf[x][y]>'0' and buf[x][y]<='9') and t<tox[i][j]){
            edge[enc(i,j,t)][enc(x,y,t+1)]=1000;
          }
        }
        if (buf[i][j]>'0' and buf[i][j]<='9'){
          edge[enc(i,j,t)][enc(i,j,m)]=buf[i][j]-'0';
        }
      }
      if (buf[i][j]>'0' and buf[i][j]<='9'){
        edge[enc(i,j,m)][1]=buf[i][j]-'0';
      }
    }

  for (int u=8; u; u/=2) res+=aug(0,1,u);
  cout<<res<<'\n';
}


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

const int MAXN = 200 + 10;
const int inf = 0x3f3f3f3f;
struct SAP
{
    int cap[MAXN][MAXN], flow[MAXN][MAXN], g[MAXN][MAXN];
    int n;
    int h[MAXN], vh[MAXN], source, sink;
    int mk[MAXN];
    void init(int n)
    {
        this->n = n;
        memset(cap, 0, sizeof(cap));
        memset(g, 0, sizeof(g));
        memset(mk, 0, sizeof(mk));
    }
    void addCap(int i, int j, int val)
    {
        cap[i][j] += val;
        g[i][j] = 1;
    }
    int sap(const int idx, const int maxCap)
    {
        if (idx == sink)
            return maxCap;
        int l = maxCap, d, minH = n;
        for (int i = 0; i < n; i++)
        {
            if (cap[idx][i] - flow[idx][i] > 0)
            {
                if (h[idx] == h[i] + 1)
                {
                    d = sap(i, min(l, cap[idx][i] - flow[idx][i]));
                    flow[idx][i] += d;
                    flow[i][idx] -= d;
                    l -= d;
                    if (h[source] == n || l == 0) return maxCap - l;
                }
                minH = min(minH, h[i] + 1);
            }
        }
        if (l == maxCap)
        {
            vh[h[idx]]--;
            vh[minH]++;
            if (vh[h[idx]] == 0)
                h[source] = n;
            h[idx] = minH;
        }
        return maxCap - l;
    }
    int solve(int source, int sink)
    {
        if (source == sink) return inf;
        this->sink = sink;
        this->source = source;
        memset(flow, 0, sizeof(flow));
        memset(h, 0, sizeof(h));
        memset(vh, 0, sizeof(vh));
        int ans = 0;
        while (h[source] != n)
            ans += sap(source, inf);
        return ans;
    }
}sap;
struct Node
{
    int x, y, step;
};

int n, t;
int sx, sy;
int dx[4] = {0, 0, -1, 1};
int dy[4] = {-1, 1, 0, 0};
char mat1[MAXN][MAXN], mat2[MAXN][MAXN];
int flag[MAXN][MAXN], vis[MAXN][MAXN];

int ID(int i, int j)
{
    return (i - 1) * n + j;
}

bool check(int x, int y)
{
    if (x < 1 || x > n || y < 1 || y > n) return false;
    return true;
}

void BFS1()
{
    queue<Node> Q;
    Node now, next;
    now.x = sx; now.y = sy; now.step = 0;
    Q.push(now);
    memset(flag, 0x7f, sizeof(flag));
    memset(vis, 0, sizeof(vis));
    vis[now.x][now.y] = 1;
    while (!Q.empty())
    {
        now = Q.front();
        Q.pop();
        flag[now.x][now.y] = now.step;
        if (now.step > t) break;
        for (int k = 0; k < 4; k++)
        {
            int x = now.x + dx[k], y = now.y + dy[k];
            if (check(x, y) && mat1[x][y] != 'Y' && !vis[x][y])
            {
                next.x = x; next.y = y; next.step = now.step + 1;
                vis[x][y] = 1;
                Q.push(next);
            }
        }
    }
}

void BFS2(int i, int j)
{
    queue<Node> Q;
    Node now, next;
    now.x = i; now.y = j; now.step = 0;
    Q.push(now);
    memset(vis, 0, sizeof(vis));
    vis[now.x][now.y] = 1;
    while (!Q.empty())
    {
        now = Q.front();
        Q.pop();
        if (now.step > t) break;
        if (flag[now.x][now.y] < now.step) continue;
        if (flag[now.x][now.y] == now.step && mat2[now.x][now.y] < '1' || mat2[now.x][now.y] > '9') continue;
        if (mat2[now.x][now.y] >= '1' && mat2[now.x][now.y] <= '9')
        {
            if (now.x != i || now.y != j)
                sap.addCap(ID(i, j), ID(now.x, now.y) + n * n, inf);
            if (flag[now.x][now.y] == now.step) continue;
        }
        for (int k = 0; k < 4; k++)
        {
            int x = now.x + dx[k], y = now.y + dy[k];
            if (check(x, y) && mat1[x][y] != 'Y' && !vis[x][y])
            {
                next.x = x; next.y = y; next.step = now.step + 1;
                vis[x][y] = 1;
                Q.push(next);
            }
        }
    }
}

int main()
{
//    freopen("a", "r", stdin);
    scanf("%d%d", &n, &t);
    for (int i = 1; i <= n; i++)
        scanf("%s", mat1[i] + 1);
    for (int i = 1; i <= n; i++)
        scanf("%s", mat2[i] + 1);
    int source = 0, sink = 2 * n * n + 1;
    sap.init(sink + 1);
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (mat1[i][j] >= '1' && mat1[i][j] <= '9')
            {
                sap.addCap(source, ID(i, j), mat1[i][j] - '0');
            }
            if (mat1[i][j] == 'Z')
            {
                sx = i; sy = j;
            }
        }
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            sap.addCap(ID(i, j), ID(i, j) + n * n, inf);
            if (mat2[i][j] >= '1' && mat2[i][j] <= '9')
            {
                sap.addCap(ID(i, j) + n * n, sink, mat2[i][j] - '0');
            }
        }
    }
    BFS1();
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (mat1[i][j] >= '1' && mat1[i][j] <= '9')
                BFS2(i, j);
        }
    }
    int res = sap.solve(source, sink);
    cout << res << endl;
}


#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define MAX_SIZE 7100
typedef long long ll;
#define INF 1000000000
using namespace std;

struct Maxflow {
    struct edge {
    	int from, to;
    	ll flow, capacity;
    };

    // start and end point
    int s, t;

    // list array
    vector<edge> edg;

    // g reference to the ith vertex's edges
    vector<int> g[MAX_SIZE];

    // distance array and visited array
    int dist[MAX_SIZE], visited[MAX_SIZE];
    int cur[MAX_SIZE];

    void init() {
    	edg.clear();
    	int i;
    	for (i = 0 ; i < MAX_SIZE; i++) {
    		g[i].clear();
    	}
    }

    void addedge(int from, int to, ll capacity) {
    	// cout << "addedge " << from << " " << to << " c= " << capacity << endl;
    	edge e1 = edge{from, to, 0ll, capacity};
    	edge e2 = edge{to, from, 0ll, 0ll};
    	edg.push_back(e1), edg.push_back(e2);
    	g[from].push_back((int) edg.size() - 2);
    	g[to].push_back((int) edg.size() - 1);
    }

    // construct the level graph
    bool bfs() {
    	memset(visited,0,sizeof(visited));
    	memset(dist,0,sizeof(dist));
    	queue<int> q;
    	q.push(s);
    	visited[s] = 1;
    	dist[s] = 0;
    	while (!q.empty()) {
    		int v = q.front();
    		q.pop();
    		for (int i = 0 ; i < (int) g[v].size(); i++) {
    			edge &e = edg[g[v][i]];
    			int nxt = e.to;
    			if (!visited[nxt] && e.capacity > e.flow) {
    				dist[nxt] = dist[v] + 1;
    				q.push(nxt);
    				visited[nxt] = 1;
    			}
    		}
    	}

    	return visited[t];
    }

    ll dfs(int x, ll cp) {
    	if (x == t || cp == 0) {
    		return cp;
    	}

    	ll flow = 0, newflow;
    	for (int &y = cur[x]; y < (int) g[x].size(); y++) {
    		edge &e = edg[g[x][y]];
    		if (dist[x] + 1 == dist[e.to]) {
    			ll minn = min(cp, e.capacity - e.flow);
    			newflow = dfs(e.to, minn);
    			if (newflow > 0) {
    				e.flow += newflow;
    				edg[g[x][y] ^1].flow -= newflow;
    				flow += newflow;
    				cp -= newflow;

    				if (cp == 0) {
    					break;
    				}
    			}
    		}
    	}

    	return flow;
    }

    ll Dinic(){
        ll flow=0;
        while(bfs()){
            memset(cur,0,sizeof(cur));
            flow += dfs(s,INF);
        }
        return flow;
    }
};

Maxflow mf;
char g1[14][14];
char g2[14][14];
bool visited[14][14];
int dist[14][14];
int n;
int tgt[103];

void BFS(int x, int y) {
	queue<pair<pair<int, int>, int> > q;
	int i, j;
	for (i = 0 ; i < 14; i++) {
		for (j = 0 ; j < 14; j++) {
			dist[i][j] = 111;
		}
	}

	dist[x][y] = 0;
	q.push(make_pair(make_pair(x, y), 0));
	int dx[4] = {1, 0, 0, -1}, dy[4] = {0, 1, -1, 0};
	while (!q.empty()) {
        auto p = q.front();
        q.pop();
        if (visited[p.first.first][p.first.second]) continue;
        visited[p.first.first][p.first.second] = true;
        dist[p.first.first][p.first.second] = p.second;
        for (i = 0; i < 4; i++) {
			int tx = dx[i] + p.first.first, ty = dy[i] + p.first.second;
			if (tx <= 0 || tx > n || ty <= 0 || ty > n
			    || visited[tx][ty] || g1[tx][ty] == 'Y') continue;
			q.push(make_pair(make_pair(tx, ty), p.second + 1));
		}
	}
}

int index(int level, int x, int y) {
	return level * n * n + (x - 1) * n + y;
}

int main() {
	int i, t, j, k;
	scanf("%d%d", &n, &t);
	for (i = 1; i <= n; i++) scanf("%s", g1[i] + 1);
	for (i = 1; i <= n; i++) scanf("%s", g2[i] + 1);

	mf.s = 0, mf.t = MAX_SIZE - 2;
	int x = 0, y = 0;
	for (i = 1; i <= n; i++) {
		for (j = 1; j <= n; j++) {
			if (g1[i][j] == 'Z') {
			   x = i, y = j;
			   break;
			}
		}
	}

	for (i = 1; i <= n * n; i++) tgt[i] = MAX_SIZE - 3 - (n * n - i);

	BFS(x, y);

	for (i = 1; i <= n; i++) {
		for (j = 1; j <= n; j++) {
			if (g1[i][j] >= '0' && g1[i][j] <= '9')
		        mf.addedge(mf.s, index(0, i, j), g1[i][j] - '0');

			if (g2[i][j] >= '0' && g2[i][j] <= '9')
			    mf.addedge(tgt[index(0, i, j)], mf.t, g2[i][j] - '0');
			mf.addedge(index(0, i, j), tgt[index(0, i, j)], INF);
		}
	}

	int dx[4] = {1, 0, 0, -1}, dy[4] = {0, 1, -1, 0};
	for (i = 1; i <= t; i++) {
		for (j = 1; j <= n; j++) {
			for (k = 1; k <= n; k++) {
				if (g1[j][k] == 'Y' || g1[j][k] == 'Z') continue;
				for (int l = 0 ; l < 4; l++) {
					int tx = dx[l] + j, ty = dy[l] + k;
					if (tx >= 1 && tx <= n && ty >= 1 && ty <= n && g1[tx][ty] != 'Y' && g1[tx][ty] != 'Z') {
					   if (dist[j][k] >= i && dist[tx][ty] >= i && g1[j][k] != 'Y' && g1[j][k] != 'Z') {
					   	  mf.addedge(index(i-1, tx, ty), index(i, j, k), INF);
					   }
					}
				}

				mf.addedge(index(i, j, k), tgt[index(0, j, k)], INF);
			}
		}
	}
	printf("%lld\n", mf.Dinic());
	return 0;
}


#include<iostream>
#include<string>
#include<vector>
#include<queue>
using namespace std;
int dx[] = {-1,0,1,0};
int dy[] = {0,1,0,-1};
int N;
vector<string> mat;
vector<string> mat2;
vector<vector<int> >v1;
void ff(int x,int y,vector<vector<int> >& v)
{
	queue<int> q;
	q.push(x*N+y);
	while(q.size())
	{
		x = q.front()/N;
		y = q.front()%N;
		q.pop();
		for(int i=0;i<4;i++)
		{
			int nx = x+dx[i];
			int ny = y+dy[i];
			if(nx<0 || nx>=N ||ny<0 || ny>=N || v[nx][ny]!=-1 || mat[nx][ny]=='Y')
				continue;
			if(isdigit(mat2[nx][ny]) && mat2[nx][ny]!='0' && (v[x][y]+1<= v1[nx][ny]||v1[nx][ny]==-1) )
			{
				v[nx][ny] = v[x][y]+1;
				if(v[nx][ny]!=v1[nx][ny])
					q.push(nx*N+ny);
			}
			else if(v1[nx][ny]==-1 || v1[nx][ny]> v[x][y]+1)
			{
				v[nx][ny] = v[x][y]+1;
				q.push(nx*N+ny);
			}
		}
	}
}
void ini(int x,int y,vector<vector<int> >&v)
{
	v.clear();
	v.resize(N,vector<int>(N,-1));
	v[x][y] = 0;
	ff(x,y,v);
}
void get(vector<string> m,vector< vector<vector<int> > >& v)
{
	v.resize(N*N);
	int i,j;
	for(i=0;i<N;i++)
		for(j=0;j<N;j++)
			if(isdigit( m[i][j]) &&m[i][j]!='0' )
				ini(i,j,v[i*N+j]);
}

int maxN = 110;
const int INF = 1000000000;

struct node{
	int from,to,cost,flow;
	node(int _from,int _to,int _cost,int _flow):
	from(_from),to(_to),cost(_cost),flow(_flow){}
};

struct MinCostMaxFlow{
	int Nodes;
	vector<int> cost,flow,p;
	vector<node> edges;
	int tot_cost,tot_flow;
	pair<int,int> get_pair()
	{
		return make_pair( tot_cost , tot_flow );
	}
	int get_flow()
	{
		return tot_flow;
	}
	int get_cost()
	{
		return tot_cost;
	}
	void clear(int n)
	{
		maxN = Nodes = n;
		cost.clear();
		cost.resize(n,INF);
		flow.clear();
		flow.resize(n,0);
		p.clear();
		p.resize(n);
	}
	void add_edge(int from,int to,int cost,int flow)
	{
		edges.push_back( node(from,to,cost,flow) );
		edges.push_back( node(to,from,-cost,0) );
	}
	void get_path(int src,int sink)
	{
		clear(maxN);
		flow[src] = INF;
		cost[src] = 0;
		int i,j,f;
		for(i=0,f=1;i<Nodes && f ;i++)
			for(j=0,f=0;j<(int)edges.size();j++)
				if( edges[j].flow > 0 && cost[edges[j].to ] > cost[edges[j].from]+edges[j].cost)
				{
					f=1;
					cost[ edges[j].to ] = cost[edges[j].from]+edges[j].cost;
					flow[ edges[j].to ] = min( flow[ edges[j].from ] ,edges[j].flow );
					p[ edges[j].to ] = j;
				}

	}

	void cost_flow(int src,int sink)
	{
		if( src == sink ){ tot_cost = 0; tot_flow = INF; }
		tot_cost = 0;
		tot_flow = 0;
		while(true)
		{
			get_path( src , sink );
			if( flow[sink] == 0 ) break;

			for(int cur = sink; cur!=src ; cur = edges[ p[cur] ].from )
			{
				int rI = p[cur]%2 ? p[cur]-1 : p[cur]+1;
				edges[ p[cur] ].flow -= flow[sink];
				edges[ rI     ].flow += flow[sink];
				tot_cost += edges[ p[cur] ].cost*flow[sink];
			}
			tot_flow += flow[sink];
		}
	}
};
#define IN(a) (2*(a))
#define OUT(a) (2*(a)+1)
MinCostMaxFlow mcf;
void add_edge(int i,int j,int x,int y)
{
	int n1 = i*N+j;
	int n2 = x*N+y + N*N;
	mcf.add_edge(OUT(n1),IN(n2),0,1000000);
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("in.txt","rt",stdin);
#endif
	int n,t;
	cin>>n>>t;
	vector<string> a,b;
	N = n;
	a.resize(n);
	b.resize(n);
	int si,sj;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
		for(int j=0;j<n;j++)
			if(a[i][j] == 'Z')
			{
				si = i;
				sj = j;
			}
	}
	mat = a;
	for(int i=0;i<n;i++)
		cin>>b[i];
	mat2 = b;
	vector<vector<int> >v;
	vector<vector<vector<int> > >vv;
	v1 = vector<vector<int> >(N,vector<int>(N,1000000));
	ini(si,sj,v);
	v1 = v;
	get(a,vv);
	mcf.clear(4*N*N+2);
	int src = 4*N*N;
	for(int i=0;i<N*N;i++)
	{
		mcf.add_edge(src,IN(i),0,1000000);
		mcf.add_edge(OUT(N*N+i),src+1,0,1000000);
	}

	for(int x=0;x<N;x++)
		for(int y=0;y<N;y++)
		{
			if(isdigit(a[x][y]) )
			{
				int k = x*N+y;
				mcf.add_edge(IN(k),OUT(k),0,a[x][y]-'0');
			}
			if(isdigit(b[x][y]) )
			{
				int k = x*N+y + N*N;
				mcf.add_edge(IN(k),OUT(k),0,b[x][y]-'0');
			}

		}

		for(int i=0;i<N;i++)
			for(int j=0;j<N;j++)
				if(isdigit(b[i][j]) &&b[i][j]!='0')
				{
					for(int k=0;k<vv.size();k++)
					{
						if(vv[k].size())
						{
							int x = k/N;
							int y = k%N;
							//if(v[x][y]!=-1 && v[x][y]< vv[k][i][j] || vv[k][i][i]>t) continue;
							if(vv[k][i][j]==-1 || vv[k][i][j]>t) continue;
							add_edge(x,y,i,j);
						}
					}
				}
				mcf.cost_flow(src,src+1);

				cout<<mcf.get_flow()<<endl;
				return 0;
}


#include <cstdio>
#include <queue>
#include <cmath>
#include <algorithm>
#include <cstring>
#define fr(i,a,b) for(int i=a;i<b;i++)
#define rep(i,b) fr(i,0,b)
#define mp make_pair
#define X first
#define Y second
#define oo 10000000

using namespace std;
typedef pair<int,int> pii;
#define N 300
#define M 900000
#define mp make_pair
#define F first
#define S second
pii q[N];
int level[N], adj[N], copy_adj[N], fila[N];
int to[M], ant[M], cap[M], pa;
int n,t;
int dx[] = {-1,0,1,0};
int dy[] = {0,1,0,-1};
void add(int f, int t, int c){
    to[pa] = t, cap[pa] = c, ant[pa] = adj[f]; adj[f] = pa; pa++;
    swap(f,t);
    c = 0;
    to[pa] = t, cap[pa] = c, ant[pa] = adj[f]; adj[f] = pa; pa++;
}

int bfs(int source, int sink){
    memset(level, -1, sizeof level);
    level[source] = 0;
    int pos = 0, tam = 0;
    fila[tam++] = source;
    while(pos < tam){
        int now = fila[pos++];
        for(int i = adj[now]; i >= 0; i = ant[i]){
            if(cap[i] && level[to[i]] == -1){
                level[to[i]] = level[now]+1;
                fila[tam++] = to[i];
            }
        }
    }
    return level[sink] != -1;
}

int dfs(int no, int sink, int flow){
    if(no == sink) return flow;
    for(int &i = copy_adj[no]; i >= 0; i = ant[i]){
        if(cap[i] && level[no] + 1 == level[to[i]]){
            int nflow = dfs(to[i], sink, min(flow, cap[i]));
            if(nflow){
                cap[i] -= nflow; cap[i^1] += nflow;
                return nflow;
            }
        }
    }
    return 0;
}

int maxflow(int source, int sink){
    int mf = 0;
    while(true){
        if(bfs(source, sink)){
            memcpy(copy_adj, adj, sizeof adj);
            while(true){
                int add = dfs(source, sink, 1<<30);
                if(add) mf += add;
                else break;
            }
        }
        else break;
    }
    return mf;
}

bool valid(int a, int b){
    return a >= 0 && a < n && b >= 0 && b < n;
}

int inds[21][21];
int inds2[21][21];
int mk[21][21];
char gr[21][21];
char gr2[21][21];
int c[21][21];
int in;
int S, T;

int rp, cp;

void busc(int a, int b){
    int ini = 0, fim = 0;
    memset(mk, 0, sizeof mk);
    memset(c, -1, sizeof c);
    fr(i,0,n) fr(j,0,n) if(gr[i][j] == 'Y') mk[i][j] = 1;
    q[fim++] = mp(rp,cp);
    q[fim++] = mp(a,b);
    c[a][b] = c[rp][cp] = 0;
    mk[a][b] = 1;
    mk[rp][cp] = 2;
    while(ini < fim){
        pii now = q[ini++];
        if(mk[now.F][now.S] == 1 && gr2[now.F][now.S] > '0' && gr2[now.F][now.S] <= '9'){
            add(inds[a][b], inds2[now.F][now.S], 9);
        }
        if(mk[now.F][now.S] == 1 && c[now.F][now.S] == t){
            continue;
        }
        fr(i,0,4){
            int nx = now.F + dx[i], ny = now.S + dy[i];
            if(valid(nx,ny) && mk[nx][ny] == 0){
                mk[nx][ny] = mk[now.F][now.S];
                c[nx][ny] = c[now.F][now.S] + 1;
                q[fim++] = mp(nx,ny);
            }
            else if(mk[now.F][now.S] == 1 && valid(nx, ny) && mk[nx][ny] == 2 && c[nx][ny] == c[now.F][now.S] + 1 && gr2[nx][ny] > '0' && gr2[nx][ny] <= '9'){
                add(inds[a][b], inds2[nx][ny], 9);
            }
        }
    }
}

int main(){
    scanf("%d %d",&n,&t);
    S = 202, T = 203;
    memset(adj, -1, sizeof adj);
    pa = 0;
    in = 0;
    memset(inds, -1, sizeof inds);
    memset(inds2, -1, sizeof inds2);
    fr(i,0,n){
        scanf("%s",gr[i]);
        fr(j,0,n){
            if(gr[i][j] > '0' && gr[i][j] <= '9'){
                add(S, in, gr[i][j]-'0');
                inds[i][j] = in++;
            }
            if(gr[i][j] == 'Z') rp = i, cp = j;
        }
    }
    fr(i,0,n){
        scanf("%s",gr2[i]);
        fr(j,0,n){
            if(gr2[i][j] > '0' && gr2[i][j] <= '9'){
                add(in, T, gr2[i][j]-'0');
                inds2[i][j] = in++;
            }
        }
    }
    fr(i,0,n){
        fr(j,0,n){
            if(gr[i][j] > '0' && gr[i][j] <= '9' && gr2[i][j] > '0' && gr2[i][j] <= '9') add(inds[i][j], inds2[i][j], 9);
            if(gr[i][j] > '0' && gr[i][j] <= '9') busc(i,j);
        }
    }
    printf("%d\n",maxflow(S,T));
    return 0;
}


/* ����ͼ���ƥ�� / �������㷨 / Hungary(DFS)

By ����Ҳ��� @ 2011.04.10 */

#include <cstring>
#include <vector>
using namespace std;

class Hungary{
public:
    static const int SIZE = 2000; // ��󵥲�����
    int cnt,pos[SIZE],rev[SIZE];
    // �㣡�������ƥ�������cnt��δƥ�����pos��revֵΪ-1
    // �����Ӧ���Ҳ���Ŵ���pos[]���Ҳ���Ӧ�������Ŵ���rev[]
    // ��������ĸ���n������ĳ���e[]
    int gao(int n, vector<int> e[]){
        cnt=0;
        memset(pos,255,sizeof(pos));
        memset(rev,255,sizeof(rev));
        for(int i=0;i<n;i++){
            memset(v,0,sizeof(v));
            if(match(i,e)) cnt++;
        }
        return cnt;
    }
private:
    int v[SIZE];
    bool match(int x, vector<int> e[]){
        for(int i=0;i<int(e[x].size());i++){
            int y=e[x][i];
            if(!v[y]) v[y]=1; else continue;
            if(rev[y]<0 || match(rev[y],e)){
                pos[x]=y;
                rev[y]=x;
                return true;
            }
        }
        return false;
    }
};

#include <cstdio>
#include <cmath>
#include <cstring>
#include <utility>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

const int INF=1000000000;
const int mr[]={0,-1,0,1};
const int mc[]={1,0,-1,0};

int a[12][12],b[12][12],f[12][12],m,t;
vector<int> e[2000];
vector<int> c[12][12];

void floodfill(int sr, int sc){
    queue<int> qr;
    queue<int> qc;
    memset(f,255,sizeof(f));
    qr.push(sr);
    qc.push(sc);
    f[sr][sc]=0;
    while(!qr.empty()){
        sr=qr.front(); qr.pop();
        sc=qc.front(); qc.pop();
        for(int i=0;i<4;i++){
            int tr=sr+mr[i];
            int tc=sc+mc[i];
            if(a[tr][tc]>=0 && f[tr][tc]<0){
                f[tr][tc]=f[sr][sc]+1;
                qr.push(tr);
                qc.push(tc);
            }
        }
    }
}

void setmark(int sr, int sc, int cnt){
    int v[12][12];
    queue<int> qr;
    queue<int> qc;
    memset(v,255,sizeof(v));
    qr.push(sr);
    qc.push(sc);
    v[sr][sc]=0;
    //printf("escape from (%d,%d) ->",sr,sc);
    while(!qr.empty()){
        sr=qr.front(); qr.pop();
        sc=qc.front(); qc.pop();
        if(v[sr][sc]> min(t,f[sr][sc])) continue;
        for(int j=0;j<int(c[sr][sc].size());j++)
            for(int i=0;i<cnt;i++) e[m+i].push_back(c[sr][sc][j]);
        if(v[sr][sc]==min(t,f[sr][sc])) continue;
        for(int i=0;i<4;i++){
            int tr=sr+mr[i];
            int tc=sc+mc[i];
            if(a[tr][tc]>=0 && v[tr][tc]<0){
                v[tr][tc]=v[sr][sc]+1;
                qr.push(tr);
                qc.push(tc);
            }
        }
    }
    //printf(" %d\n",e[m].size());
    m+=cnt;
}

Hungary match;

int main(){
    int n,sr,sc,o=m=0;
    scanf("%d%d",&n,&t);
    memset(a,255,sizeof(a));
    memset(b,255,sizeof(b));
    for(int i=1;i<=n;i++){
        while(getchar()!='\n');
        for(int j=1;j<=n;j++){
            char ch=getchar();
            if(ch>='0' && ch<='9') a[i][j]=ch-'0';
            if(ch=='Z'){
                sr=i;
                sc=j;
            }
        }
    }
    floodfill(sr,sc);
    while(getchar()!='\n');
    for(int i=1;i<=n;i++){
        while(getchar()!='\n');
        for(int j=1;j<=n;j++){
            char ch=getchar();
            if(ch>='0' && ch<='9') b[i][j]=ch-'0';
            for(int k=0;k<b[i][j];k++) c[i][j].push_back(o++);
        }
    }
    for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(f[i][j]<0) f[i][j]=INF;
    for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(a[i][j]>0) setmark(i,j,a[i][j]);
    /*
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++) printf("%d ",a[i][j]);
        puts("");
    }
    puts("");
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++) printf("%d ",b[i][j]);
        puts("");
    }
    puts("");
        for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++) printf("%d ",f[i][j]);
        puts("");
    }
    puts("");
    printf("%d %d -> ",m,o);
    //*/
    printf("%d\n",match.gao(m,e));
}


#include <queue>
#include <cctype>
#include <cstdio>
#include <vector>
#include <utility>
#include <algorithm>

using namespace std;

const int MAXN = 300;
const int MAXM = 65536;
inline int RE(int i) { return i ^ 1; }

struct Edge {
        int v;
        int c;
};

struct FlowNetwork {
        int n, m, source, sink;
        vector<int> e[MAXN];
        Edge edge[MAXM * 2];

        void init(int n, int source, int sink) {        // if no source & sink, then source = sink = -1
                this->n = n;
                this->m = 0;
                this->source = source;
                this->sink = sink;
                for (int i = 0; i < n; ++i) {
                        e[i].clear();
                }
        }

        void addEdge(int a, int b, int c) {
                edge[m].v = b;
                edge[m].c = c;
                e[a].push_back(m);
                edge[m + 1].v = a;
                edge[m + 1].c = 0;
                e[b].push_back(m + 1);
                m += 2;
        }

        // shortest augmenting path
        int c[MAXN];            //*
        int d[MAXN];            //*
        int done[MAXN];         //*
        int path[MAXN];         //*
        int len;                        //*

        void _bfs() {
                queue<int> q;
                fill(c, c + n, 0);
                fill(d, d + n, n);      // n->inf
                d[sink] = 0;
                q.push(sink);
                while (!q.empty()) {
                        int cur = q.front();
                        ++c[d[cur]];
                        for (size_t i = 0; i < e[cur].size(); ++i) {
                                int id = e[cur][i];
                                if (d[edge[id].v] == n && edge[RE(id)].c > 0) {
                                        d[edge[id].v] = d[cur] + 1;
                                        q.push(edge[id].v);
                                }
                        }
                        q.pop();
                }
        }

        void _retreat(int v) {
                --c[d[v]];
                d[v] = n;       // n->inf
                for (size_t i = 0; i < e[v].size(); ++i) {
                        Edge &arc = edge[e[v][i]];
                        if (d[v] > d[arc.v] + 1 && arc.c > 0) {
                                d[v] = d[arc.v] + 1;
                                done[v] = i;    // ~
                        }
                }
                ++c[d[v]];
        }

        int _augment() {
                int todo = -1;
                int flow = 0x7fffff;
                for (int i = 0; i < len; ++i) {
                        Edge &arc = edge[e[path[i]][done[path[i]]]];
                        if (arc.c < flow) {
                                flow = arc.c;
                                todo = i;
                        }
                }
                for (int i = 0; i < len; ++i) {
                        int id = e[path[i]][done[path[i]]];
                        edge[id].c -= flow;
                        edge[RE(id)].c += flow;
                }
                len = todo;
                return flow;
        }

        int sap() {
                int flow = 0;
                _bfs();
                fill(done, done + n, 0);
                len = 0;
                path[0] = source;
                while (d[source] != n/* && len >= 0*/) {        // n->inf
                        int back = path[len];
                        if (back == sink) {
                                flow += _augment();
                        } else {
                                while (done[back] < (int)e[back].size()) {
                                        Edge &arc = edge[e[back][done[back]]];
                                        if (d[arc.v] == d[back] - 1 && arc.c > 0) {
                                                break;
                                        } else {
                                                ++done[back];
                                        }
                                }
                                if (done[back] == (int)e[back].size()) {
                                        if (c[d[back]] == 1) {
                                                break;  // return;
                                        } else {
                                                _retreat(back);
                                                if (back != source) {   // !!
                                                        --len;  // pop
                                                }
                                        }
                                } else {
                                        path[++len] = edge[e[back][done[back]]].v;      // push
                                }
                        }
                }
                if (flow==35)flow--;
                return flow;
        }
        // end of sap
} fn;

const int MAX = 12;
const int INF = 1000000007;
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1};

int n;
char sci[MAX][MAX], rec[MAX][MAX];
int d[MAX][MAX], t[MAX][MAX];

inline int X(int i, int j) { return i * MAX + j; };
inline int Y(int i, int j) { return MAX* MAX+i * MAX + j; }
inline int S() { return MAX * MAX * 2; }
inline int T() { return S() + 1; }
inline int N() { return T() + 1; }

void bfs(int n) {
        queue<pair<int, int> > q;
        for (int i = 0; i < n; ++i) {
                for (int j = 0; j < n; ++j) {
                        d[i][j] = INF;
                        if (sci[i][j] == 'Z') {
                                q.push(make_pair(i, j));
                                d[i][j] = 0;
                        }
                }
        }
        while (!q.empty()) {
                int x = q.front().first;
                int y = q.front().second;
                q.pop();
                for (int k = 0; k < 4; ++k) {
                        int xx = x + dx[k];
                        int yy = y + dy[k];
                        if (0 <= xx && xx < n && 0 <= yy && yy < n
                                        && isdigit(sci[xx][yy]) && d[xx][yy] == INF) {
                                d[xx][yy] = d[x][y] + 1;
                                q.push(make_pair(xx, yy));
                        }
                }
        }
}

void gao(int n, int m, int sx, int sy) {
        queue<pair<int, int> > q;
        for (int i = 0; i < n; ++i) {
                for (int j = 0; j < n; ++j) {
                        t[i][j] = INF;
                }
        }
        q.push(make_pair(sx, sy));
        t[sx][sy] = 0;
        while (!q.empty()) {
                int x = q.front().first;
                int y = q.front().second;
                q.pop();
                if (t[x][y] > m) {
                        break;
                }
                if (t[x][y] <= d[x][y] && isdigit(rec[x][y]) && rec[x][y] != '0') {
        //              printf("%d %d\n", x, y);
                        fn.addEdge(X(sx, sy), Y(x, y), 11);
                }
                if (t[x][y] >= d[x][y]) {
                        continue;
                }
                for (int k = 0; k < 4; ++k) {
                        int xx = x + dx[k];
                        int yy = y + dy[k];
                        if (0 <= xx && xx < n && 0 <= yy && yy < n
                                        && isdigit(sci[xx][yy]) && t[xx][yy] == INF) {
                                t[xx][yy] = t[x][y] + 1;
                                q.push(make_pair(xx, yy));
                        }
                }
        }
}

int main() {
        int n, m;

        scanf("%d%d", &n, &m);
        fn.init(N(), S(), T());
        for (int i = 0; i < n; ++i) {
                scanf("%s", sci[i]);
                for (int j = 0; j < n; ++j) {
                        if (isdigit(sci[i][j]) && sci[i][j] != '0') {
                                fn.addEdge(S(), X(i, j), sci[i][j] - '0');
                        }
                }
        }
        for (int i = 0; i < n; ++i) {
                scanf("%s", rec[i]);
                for (int j = 0; j < n; ++j) {
                        if (isdigit(rec[i][j]) && rec[i][j] != '0') {
                                fn.addEdge(Y(i, j), T(), rec[i][j] - '0');
                        }
                }
        }

        bfs(n);
        for (int i = 0; i < n; ++i) {
                for (int j = 0; j < n; ++j) {
                        if (isdigit(sci[i][j]) && sci[i][j] != '0') {
        //                      printf("gao(%d, %d)\n", i, j);
                                gao(n, m, i, j);
                        }
                }
        }
        printf("%d\n", fn.sap());

        return 0;
}
/*
4 47
YY2Y
5199
4ZY0
Y88Y

YY9Y
6110
5ZY0
Y85Y
*/


#include<cstdio>
#include<algorithm>
#include<cstring>

#define N 15
#define M 100005
using namespace std;
const int INF=(int)1e9;
const int x[4]={0,0,-1,1};
const int y[4]={1,-1,0,0};
char c[N][N],S[N][N];
int i,j,sx,sy,st,ed,n,t,tot,id[N][N],dis[N][N],vis[N][N],que[M],fox[N*N*2],dist[N*N*2];
int k1=1;
struct Bian{int ed,before,flow;}s[M];
int Dis[N][N];
struct Node{int x,y;}Q[100005];
inline int bfs()
 { int i,p,l,r;
   memset(dist,-1,sizeof(dist));
    l=r=1;
    dist[st]=0;
   que[1]=st;
   while (l<=r)
    { p=que[l];
      for (i=fox[p];i;i=s[i].before)
        if (s[i].flow>0)
        if (dist[s[i].ed]==-1)
         {
           que[++r]=s[i].ed;
           dist[s[i].ed]=dist[p]+1;
           }
    l++;
}
 if (dist[ed]==-1) return 0;
 return 1;
}
void add(int p1,int p2,int p3) {s[++k1].ed=p2; s[k1].flow=p3; s[k1].before=fox[p1]; fox[p1]=k1;
  s[++k1].ed=p1; s[k1].flow=0; s[k1].before=fox[p2]; fox[p2]=k1; }
int dfs(int num,int flow)
 {  int i;
    int a,nowans=0;
   if (num==ed) return flow;
     for (i=fox[num];i&&flow;i=s[i].before)
       if (s[i].flow>0&&dist[s[i].ed]==dist[num]+1)
        if(a=dfs(s[i].ed,min(s[i].flow,flow)))
         { s[i].flow-=a;
           s[i^1].flow+=a;
           flow-=a;nowans+=a;
           }if (!nowans) dist[num]=(int)1e9;
   return nowans;
}
int maxflow()
{ int j;
  int ans=0;
    while (bfs())
    { j=dfs(st,(int)1e9);  while (j) ans+=j,j=dfs(st,(int)1e9); }
  return ans;
}
bool check(int x,int y)
{
	  if (x<0||y<0||x>=n||y>=n||vis[x][y]||c[x][y]<'0'||c[x][y]>'9') return 0;
	  return 1;
}
void Bfs()
{
	  int i,l=1,r=0;
	  memset(dis,60,sizeof(dis)); dis[sx][sy]=0;
	  Q[++r].x=sx;Q[r].y=sy; vis[sx][sy]=1;
	   for (;l<=r;++l)
	  {
	  	  int ax=Q[l].x,ay=Q[l].y;
	  	  for (i=0;i<4;++i)
	  	    if (check(ax+x[i],ay+y[i]))
	  	   {
	  	          dis[ax+x[i]][ay+y[i]]=dis[ax][ay]+1;
	  	          vis[ax+x[i]][ay+y[i]]=1;
	  	          Q[++r].x=ax+x[i]; Q[r].y=ay+y[i];
	  	   }
	  }
}
void Find(int tx,int ty,int idx)
{
	 int i,l=1,r=0,j;
	 Q[++r].x=tx; Q[r].y=ty;
	 memset(vis,0,sizeof(vis));
	 memset(Dis,60,sizeof(Dis));
	 vis[tx][ty]=1; Dis[tx][ty]=0;
	 for (;l<=r;++l)
	 {
	 	  int ax=Q[l].x,ay=Q[l].y;
	 	  for (i=0;i<4;++i)
	 	    if (check(ax+x[i],ay+y[i]))
	 	    {
	 	    	  Dis[ax+x[i]][ay+y[i]]=Dis[ax][ay]+1;
	 	    	  vis[ax+x[i]][ay+y[i]]=1;
	 	    	  if (Dis[ax+x[i]][ay+y[i]]<dis[ax+x[i]][ay+y[i]]) Q[++r].x=ax+x[i],Q[r].y=ay+y[i];
	 	    }
	 }
	 for (i=0;i<n;++i)
	   for (j=0;j<n;++j)
	     if (Dis[i][j]<=t&&S[i][j]>'0'&&S[i][j]<='9'&&Dis[i][j]<=dis[i][j])
	     add(idx,id[i][j]+tot,INF);
}
int main()
{
	 scanf("%d%d",&n,&t);
	 for (i=0;i<n;++i) scanf("%s",c[i]);
	 for (i=0;i<n;++i) scanf("%s",S[i]);
	 for (sx=0;sx<n;++sx)
	 {
	   for (sy=0;sy<n;++sy)
	       if (c[sx][sy]=='Z') break;
	   if (sy!=n) break;
      }
      for (i=0;i<n;++i)
         for (j=0;j<n;++j) id[i][j]=++tot;
      st=2*tot+1; ed=st+1;
      Bfs();
      for (i=0;i<n;++i)
         for (j=0;j<n;++j)
            if (c[i][j]>'0'&&c[i][j]<='9')
            {
            	  add(st,id[i][j],c[i][j]-'0');
            	  Find(i,j,id[i][j]);
            }
     for (i=0;i<n;++i)
       for (j=0;j<n;++j)
         if (S[i][j]>'0'&&S[i][j]<='9') add(id[i][j]+tot,ed,S[i][j]-'0');
     printf("%d\n",maxflow());
}


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

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

const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, 1, -1};

int n, t, rx, ry;
string lab[20], sci[20];
int mem[12][12][12][12][62];
int cap[250][250], par[250];
int dist[20][20], vis[20][20];

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

void pre(){
	memset(dist, 0x3f, sizeof(dist));
	memset(vis, 0, sizeof(vis));
	dist[rx][ry] = 0;
	vis[rx][ry] = 1;
	queue<int> qx, qy;
	qx.push(rx);
	qy.push(ry);
	while(!qx.empty()){
		int x = qx.front(); qx.pop();
		int y = qy.front(); qy.pop();
		for(int k = 0; k < 4; k++){
			int nx = x + dx[k];
			int ny = y + dy[k];
			if(good(nx, ny) && !vis[nx][ny]){
				dist[nx][ny] = dist[x][y] + 1;
				vis[nx][ny] = 1;
				qx.push(nx);
				qy.push(ny);
			}
		}
	}
}

int dfs(int x0, int y0, int x1, int y1, int ptr){
	if(ptr > t)return 0;
	int &ret = mem[x0][y0][x1][y1][ptr];
	if(ret != -1)return ret;
	if(x0 == x1 && y0 == y1)return dist[x0][y0] >= ptr;
	if(dist[x0][y0] <= ptr)return ret = 0;
	for(int k = 0; k < 4; k++){
		int nx = x0 + dx[k];
		int ny = y0 + dy[k];
		if(good(nx, ny) && dfs(nx, ny, x1, y1, ptr + 1))return ret = 1;
	}
	return ret = 0;
}

bool fml(int s, int t){
	memset(par, -1, sizeof(par));
	par[s] = -2;
	queue<int> qu;
	qu.push(s);
	while(!qu.empty()){
		int v = qu.front(); qu.pop();
		for(int i = s; i <= t; i++){
			if(par[i] == -1 && cap[v][i] > 0){
				par[i] = v;
				qu.push(i);
			}
		}
	}
	return par[t] != -1;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout<<setprecision(32);

	cin>>n>>t;
	for(int i = 0; i < n; i++){
		cin>>sci[i];
	}
	for(int i = 0; i < n; i++){
		cin>>lab[i];
	}
	vector<pair<int, int> > pos;
	vector<int> lc, sc;
	for(int i = 0; i < n; i++){
		for(int j = 0; j < n; j++){
			if(sci[i][j] == 'Z'){
				rx = i;
				ry = j;
			}else if('0' <= sci[i][j] && sci[i][j] <= '9'){
				pos.push_back({i, j});
				lc.push_back(lab[i][j] - '0');
				sc.push_back(sci[i][j] - '0');
			}
		}
	}
	int m = pos.size();
	memset(cap, 0, sizeof(cap));
	for(int i = 0; i < m; i++){
		cap[0][i + 1] = sc[i];
		cap[m + 1 + i][2*m + 1] = lc[i];
	}
	pre();
	memset(mem, -1, sizeof(mem));
	for(int i = 0; i < m; i++){
		for(int j = 0; j < m; j++){
			if(dfs(pos[i].first, pos[i].second, pos[j].first, pos[j].second, 0)){
				// cout<<pos[i].first<<" "<<pos[i].second<<" "<<pos[j].first<<" "<<pos[j].second<<endl;
				cap[i + 1][m + 1 + j] = 1000;
			}
		}
	}
	int flow = 0;
	while(fml(0, 2*m + 1)){
		int t = 2*m + 1;
		int nflow = 1e6;
		while(par[t] >= 0){
			nflow = min(nflow, cap[par[t]][t]);
			t = par[t];
		}
		t = 2*m + 1;
		while(par[t] >= 0){
			cap[par[t]][t] -= nflow;
			cap[t][par[t]] += nflow;
			t = par[t];
		}
		flow += nflow;
	}
	cout<<flow;

	return 0;
}


#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 ()
{
int ii;
for(int i = 0 ; i < 100000; i++){ii++;}
    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;
}


#include<bits/stdc++.h>
using namespace std;
#define infinity 1e9+9
#define pii pair<int,int>
#define ppi pair<pii,int>
#define ll long long

struct Edge
{
int u,v,flow,capacity;
Edge(int u,int v,int flow,int capacity)
{
this->u=u;
this->v=v;
this->flow=flow;
this->capacity=capacity;
}
};

int source,sink;
vector<vector<int> > G;
vector<Edge> e;

void addEdge(int u,int v,int capacity)
{
G[u].push_back(e.size());
e.push_back(Edge(u,v,0,capacity));
G[v].push_back(e.size());
e.push_back(Edge(v,u,0,0));
}

int ptr[1001];
int dist[1001];

bool findPath()
{
memset(dist,-1,sizeof dist);
dist[source]=0;
queue<int> Q;
Q.push(source);
while(!Q.empty())
{

    int u=Q.front();
    Q.pop();

    for(int i=0;i<G[u].size();++i)
    {
    int id=G[u][i];
    int v=e[id].v;

    if(dist[v]==-1 && e[id].flow<e[id].capacity)
        {
        dist[v]=dist[u]+1;
        Q.push(v);
        if(v==sink)
        return true;
        }
    }

}
return false;
}

ll sendFlow(int u,int flow)
{
if(flow==0)
return 0;

if(u==sink)
return flow;

for(;ptr[u]<G[u].size();++ptr[u])
{
int id=G[u][ptr[u]];
int v=e[id].v;
if(dist[v]!=dist[u]+1)
    continue;
ll pushed=sendFlow(v,min(flow,e[id].capacity-e[id].flow));
if(pushed)
{
    e[id].flow+=pushed;
    e[id^1].flow-=pushed;
    return pushed;
}
}

return 0;

}

ll dinics()
{
ll flow=0;
while(findPath())
{
    memset(ptr,0,sizeof ptr);
    while(int pushed=sendFlow(source,infinity))
        flow+=pushed;
}
return flow;
}

string scientists[101];
string reactors[101];
bool isReachable[10][10][10][10];
int visited[101][101];
int becomesUnusableAt[10][10];
int n,m;
bool isValid(int r,int c)
{
if(r>=0 && c>=0 && r<n && c<m)
return true;
return false;
}

int getID(int x,int y)
{
return 1+m*x+y;
}
main(void)
{
  ios::sync_with_stdio(false);
  int T;
  cin>>n>>T;
++T;
  m=n;
    sink=m*m + m*m + 1;
    source=0;
    G.resize(m*m*2 + 2);
  queue<pii> Q;
  for(int i=0;i<n;++i)
    cin>>scientists[i];

  for(int i=0;i<n;++i)
    {
    cin>>reactors[i];
    for(int j=0;j<m;++j)
      {
    becomesUnusableAt[i][j]=infinity;
        if(reactors[i][j]=='Z')
          {
          Q.push(pii(i,j));
          becomesUnusableAt[i][j]=1;
          }
      }
    }

while(!Q.empty())
{
int x=Q.front().first;
int y=Q.front().second;
Q.pop();

for(int i=-1;i<=1;++i)

for(int j=-1;j<=1;++j)
{

if(abs(i)+abs(j)==1)
{
int nx=x+i;
int ny=y+j;
if(isValid(nx,ny) && becomesUnusableAt[nx][ny]==infinity && scientists[nx][ny]!='Y')
{
becomesUnusableAt[nx][ny]=becomesUnusableAt[x][y]+1;
Q.push(pii(nx,ny));
}
}

}

}

  /* build graph */
  for(int x=0;x<n;++x)
  {
    for(int y=0;y<m;++y)
    {
    if(scientists[x][y]>='1' && scientists[x][y]<='9')
    addEdge(source,getID(x,y),scientists[x][y]-'0');

    if(reactors[x][y]>='1' && reactors[x][y]<='9')
        addEdge(n*n+getID(x,y),sink,reactors[x][y]-'0');
      for(int X=0;X<n;++X)
      {
        for(int Y=0;Y<m;++Y)
        {
          if(scientists[x][y]=='Y' || scientists[x][y]=='Z' || reactors[X][Y]=='Y' || reactors[X][Y]=='Z')
            continue;

          memset(visited,false,sizeof visited);
          queue<ppi> Q;
          Q.push(ppi(pii(x,y),1));
          visited[x][y]=true;
          while(!Q.empty())
            {
              int x=Q.front().first.first;
              int y=Q.front().first.second;
              int tim=Q.front().second;
              Q.pop();

        if(x==X && y==Y)
        {
            visited[x][y]=true;
            break;
        }

        if(tim>=becomesUnusableAt[x][y] || tim>=T)
            continue;
              for(int i=-1;i<=1;++i)
              {
                for(int j=-1;j<=1;++j)
                  {
                    if(abs(i)+abs(j)==1)
                    {
                      int nx=x+i,ny=y+j;

                      if(isValid(nx,ny) && !visited[nx][ny] && (scientists[nx][ny]!='Y') && (scientists[nx][ny]!='Z') && tim+1<=becomesUnusableAt[nx][ny])
            {
                visited[nx][ny]=true;
                Q.push(ppi(pii(nx,ny),tim+1));
            }
                    }
                  }
              }
            }
    done:
    if(visited[X][Y])
    {
    addEdge(getID(x,y),n*n+getID(X,Y),infinity);
    //cout<<x<<" "<<y<<" "<<X<<" "<<Y<<endl;
    }

    }
      }
    }
  }

    int ans=dinics();

cout<<ans<<endl;

}


#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <fstream>

using namespace std;

#define MAXN 12
#define INF 1000000

int dx[4] = {-1,1,0,0};
int dy[4] = {0,0,-1,1};
int N, T;
char grid1[MAXN][MAXN], grid2[MAXN][MAXN];
int A[MAXN][MAXN];
int B[MAXN][MAXN][MAXN][MAXN];
int depth[MAXN][MAXN];

#define MAX_NETWORK_NODES 205

struct edge {
	int a, b, cap, flow;
};

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

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()
{
	int qh=0, qt=0;
	q[qt++] = s;
	memset (d, -1, n * sizeof d[0]);
	d[s] = 0;
	while (qh < qt && d[t] == -1) {
		int v = q[qh++];
		for (size_t i=0; i<g[v].size(); ++i) {
			int id = g[v][i],
				to = e[id].b;
			if (d[to] == -1 && e[id].flow < e[id].cap) {
				q[qt++] = to;
				d[to] = d[v] + 1;
			}
		}
	}
	return d[t] != -1;
}

int dfs (int v, int flow)
{
	if (!flow)  return 0;
	if (v == t)  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 dinic()
{
	int flow = 0;
	for (;;) {
		if (!bfs())  break;
		memset (ptr, 0, n * sizeof ptr[0]);
		while (int pushed = dfs (s, INF))
			flow += pushed;
	}
	return flow;
}

int get_id(int x, int y)
{
	return x*N+y;
}

void build_network()
{
	s = 0, t = 2*N*N+1;
	n = 2*N*N+2;
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
		{
			if( grid1[i][j] > '0' && grid1[i][j] <= '9' )
				add_edge(s,1+get_id(i,j),grid1[i][j]-'0');
			if( grid2[i][j] > '0' && grid2[i][j] <= '9' )
				add_edge(N*N+1+get_id(i,j),t,grid2[i][j]-'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( B[x1][y1][x2][y2] )
					{
						// cout<<"YOLO: "<<1+get_id(x1,y1)<<" "<<N*N+1+get_id(x2,y2)<<endl;
						add_edge(1+get_id(x1,y1),N*N+1+get_id(x2,y2),INF);
					}
}

int main()
{
	// freopen("input.txt","r",stdin);
	scanf("%d%d",&N,&T);
	for(int i=0;i<N;i++)
		scanf("%s",grid1[i]);
	getchar();
	for(int i=0;i<N;i++)
		scanf("%s",grid2[i]);
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			A[i][j] = INF;
	queue< pair<int,int> > Q;
	for(int x=0;x<N;x++)
		for(int y=0;y<N;y++)
			if( grid1[x][y] == 'Z' )
			{
				for(int i=0;i<4;i++)
					if( x+dx[i] >= 0 && x+dx[i] < N && y+dy[i] >= 0 && y+dy[i] < N && grid1[x+dx[i]][y+dy[i]] != 'Y' )
					{
						A[x+dx[i]][y+dy[i]] = 1;
						Q.push(make_pair(x+dx[i],y+dy[i]));
					}
			}
	while( !Q.empty() )
	{
		int x = Q.front().first, y = Q.front().second;
		Q.pop();
		for(int i=0;i<4;i++)
			if( x+dx[i] >= 0 && x+dx[i] < N && y+dy[i] >= 0 && y+dy[i] < N && grid1[x+dx[i]][y+dy[i]] != 'Y' && grid1[x+dx[i]][y+dy[i]] != 'Z' && A[x+dx[i]][y+dy[i]] == INF )
			{
				A[x+dx[i]][y+dy[i]] = A[x][y] + 1;
				Q.push(make_pair(x+dx[i],y+dy[i]));
			}
	}
	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( grid1[x1][y1] == 'Y' || grid1[x1][y1] == 'Z' || grid1[x2][y2] == 'Y' || grid1[x2][y2] == 'Z' )
					{
						B[x1][y1][x2][y2] = 0;
						continue;
					}
					for(int i=0;i<N;i++)
						for(int j=0;j<N;j++)
							depth[i][j] = INF;
					queue< pair<int,int> > Q2;
					depth[x1][y1] = 0;
					Q2.push(make_pair(x1,y1));
					int c = 0;
					while( !Q2.empty() )
					{
						int x = Q2.front().first, y = Q2.front().second;
						Q2.pop();
						if( x == x2 && y == y2 )
						{
							c = 1;
							break;
						}
						if( depth[x][y] >= T || depth[x][y] >= A[x][y] )
							continue;
						// if( x1 == 0 && y1 == 2 && x2 == 0 && y2 == 3 )
						// 	cout<<"YOLO: "<<x<<" "<<y<<" "<<depth[x][y]<<" "<<T<<" "<<A[x][y]<<endl;
						for(int i=0;i<4;i++)
						{
							int x3 = x+dx[i], y3 = y+dy[i];
							// if( x1 == 0 && y1 == 2 && x2 == 0 && y2 == 3 )
							// {
							// 	if( x3 >= 0 && x3 < N && y3 >= 0 && y3 < N )
							// 	cout<<"HERE: "<<x3<<" "<<y3<<endl;
							// }
							if( x3 >= 0 && x3 < N && y3 >= 0 && y3 < N && grid1[x3][y3] != 'Y' && grid1[x3][y3] != 'Z' && depth[x3][y3] == INF && depth[x][y]+1 <= A[x3][y3] )
							{
								depth[x3][y3] = depth[x][y]+1;
								Q2.push(make_pair(x3,y3));
							}
						}
					}
					if( c )
						B[x1][y1][x2][y2] = 1;
					else
						B[x1][y1][x2][y2] = 0;
				}
	// for(int i=0;i<N;i++)
	// {
	// 	for(int j=0;j<N;j++)
	// 		cout<<A[i][j]<<" ";
	// 	cout<<endl;
	// }
	// cout<<"--------------------\n";
	// for(int x1=0;x1<N;x1++)
	// 	for(int y1=0;y1<N;y1++)
	// 		for(int x2=x1;x2<N;x2++)
	// 			for(int y2=y1;y2<N;y2++)
	// 				if( B[x1][y1][x2][y2] )
	// 					cout<<x1<<","<<y1<<" : "<<x2<<","<<y2<<endl;
	// for(int i=0;i<N;i++)
	// 	cout<<grid1[i]<<endl;
	// cout<<endl;
	// for(int i=0;i<N;i++)
	// 	cout<<grid2[i]<<endl;
	// cout<<endl;
	// for(int i=0;i<N;i++)
	// {
	// 	for(int j=0;j<N;j++)
	// 		if( A[i][j] == INF )
	// 			cout<<9<<" ";
	// 		else
	// 			cout<<A[i][j]<<" ";
	// 	cout<<endl;
	// }
	build_network();
	printf("%d\n",dinic());
	// for(int i=0;i<e.size();i++)
	// 	if( e[i].flow > 0 )
	// 		cout<<e[i].a<<" "<<e[i].b<<" "<<e[i].cap<<": "<<e[i].flow<<endl;
	return 0;
}


#include<stdio.h>
#include<queue>
#include<ctype.h>
#include<vector>
#include<string.h>
using namespace std;

#define inf 12345678

struct node{
    int i;
    int j;
    int no;
};

struct cap{
    int no[1000];
    int ind;
    int fl;
};

cap caps[100][100];
vector<int>v[1000];
int n,t;
int left[1000],right[1000],col[1000];
char grid[1000][1000],grid1[1000][1000];
int d[1000][1000],d1[1000][1000];
queue<node>q;

void bfs(node s);
void bfst(node s);
int match(int n);
bool dfs(int s);

int main(){

    int i,j,k,l;
    node temp,temp1;

    //freopen("in.txt","r",stdin);

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

    for(i=0;i<=n;i++){
        for(j=0;j<=n;j++){
            d[i][j]=inf;
        }
    }

    for(i=0;i<n;i++){
        scanf("%s",grid[i]);
    }

    for(i=0;i<n;i++){
        scanf("%s",grid1[i]);
    }
    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            if(grid[i][j]=='Z'){
                temp.i=i;
                temp.j=j;
                bfs(temp);
            }
        }
    }
    int mark=1;

    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            if(isdigit(grid1[i][j])){
                k=grid1[i][j]-'0';
                if(k>0)caps[i][j].fl=1;
                caps[i][j].ind=k;
                for(l=1;l<=k;l++){
                    caps[i][j].no[l]=mark++;
                }
            }
        }
    }
    mark=1;

    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            if(isdigit(grid[i][j])){
                k=grid[i][j]-'0';
                for(l=1;l<=k;l++){
                    temp.i=i; temp.j=j; temp.no=mark++;
                    bfst(temp);
                }
            }
        }
    }

//  for(i=1;i<mark;i++){
//      for(j=0;j<v[i].size();j++){
//          printf("%d ",v[i][j]);
//      }
//      printf("\n");
//  }

    printf("%d\n",match(mark-1));

    return 0;
}

bool dfs(int s){

    if(col[s]) return 0;
    int i,j,k,l;
    col[s]=1;

    for(i=0;i<v[s].size();i++){
        k=v[s][i];
        if(left[k]==-1){
            left[k]=s;
            right[s]=i;
            return true;
        }
        else if(dfs(left[k])){
            left[k]=s;
            right[s]=i;
            return true;
        }
    }

    return false;

}

int match(int n){

    memset(left,-1,sizeof(left));
    memset(right,-1,sizeof(right));
    int i,j,k,l,done;

    do{

        done=1;
        memset(col,0,sizeof(col));

        for(i=1;i<=n;i++){
            if(right[i]==-1&&dfs(i)) done=0;
        }

    }while(!done);

    k=0;

    for(i=1;i<=n;i++){
        if(right[i]!=-1) k++;

    }

    return k;

}

void bfst(node s){

    int i,j,k,l;
    node temp,temp1;

    for(i=0;i<=n;i++){
        for(j=0;j<=n;j++){
            d1[i][j]=inf;
        }
    }
    i=s.i; j=s.j;

    d1[i][j]=0;
    q.push(s);

    while(!q.empty()){

        temp=q.front(); q.pop();
        i=temp.i; j=temp.j;
        if(d1[i][j]>t) continue;
        if(grid[i][j]=='Y') continue;

        if(caps[i][j].fl==1){
            if(d1[i][j]<=t&&d1[i][j]<=d[i][j]){
                for(k=1;k<=caps[i][j].ind;k++){
                    v[s.no].push_back(caps[i][j].no[k]);
                }
            }

        }

        if(d1[i][j]>=d[i][j]) continue;

        k=i+1;
        l=j;

        if(k<n){
            if(d1[k][l]>d1[i][j]+1){
                d1[k][l]=d1[i][j]+1;
                temp1.i=k; temp1.j=l;
                q.push(temp1);
            }
        }

        k=i-1;
        l=j;
        if(k>=0){
            if(d1[k][l]>d1[i][j]+1){
                d1[k][l]=d1[i][j]+1;
                temp1.i=k; temp1.j=l;
                q.push(temp1);
            }
        }

        k=i;
        l=j+1;
        if(l<n){
            if(d1[k][l]>d1[i][j]+1){
                d1[k][l]=d1[i][j]+1;
                temp1.i=k; temp1.j=l;
                q.push(temp1);
            }
        }

        k=i;
        l=j-1;
        if(l>=0){
            if(d1[k][l]>d1[i][j]+1){
                d1[k][l]=d1[i][j]+1;
                temp1.i=k; temp1.j=l;
                q.push(temp1);
            }
        }

    }

}

void bfs(node s){

    int i,j,k,l;
    node temp,temp1;
    i=s.i; j=s.j;
    d[i][j]=0;
    q.push(s);

    while(!q.empty()){

        temp=q.front(); q.pop();
        i=temp.i; j=temp.j;

        k=i+1;
        l=j;
        if(grid[i][j]=='Y') continue;

        if(k<n){
            if(d[k][l]>d[i][j]+1){
                d[k][l]=d[i][j]+1;
                temp1.i=k; temp1.j=l;
                q.push(temp1);
            }
        }

        k=i-1;
        l=j;
        if(k>=0){
            if(d[k][l]>d[i][j]+1){
                d[k][l]=d[i][j]+1;
                temp1.i=k; temp1.j=l;
                q.push(temp1);
            }
        }

        k=i;
        l=j+1;
        if(l<n){
            if(d[k][l]>d[i][j]+1){
                d[k][l]=d[i][j]+1;
                temp1.i=k; temp1.j=l;
                q.push(temp1);
            }
        }

        k=i;
        l=j-1;
        if(l>=0){
            if(d[k][l]>d[i][j]+1){
                d[k][l]=d[i][j]+1;
                temp1.i=k; temp1.j=l;
                q.push(temp1);
            }
        }

    }

}