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

    }

}


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

#include <vector>
#include <queue>

using namespace std;

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

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

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

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

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

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

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

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

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

#define INF 98765432

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

public:
   VVI cap;
// VVI adj;

   // OUTPUT:
   VVI flow;

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

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

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

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

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

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

   VI path;
   int res = 0;

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

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

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

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

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

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

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

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

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

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

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

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

   return 0;
}


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

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

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

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

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

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

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

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

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

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


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

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

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

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

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


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


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


#define _USE_MATH_DEFINES

#include <cmath>
#include <cstdio>

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

using namespace std;

#define mp make_pair
#define pb push_back

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

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

int tim[12][12];

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

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

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

int pN[11][11];

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

    cin >> n >> t;

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

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

    deque<pair<int,int> > q;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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


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


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

typedef long long LL;

const int inf=0x3f3f3f3f;

const int N=210;

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

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

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

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

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

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

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

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

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

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

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

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

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

    return 0;
}
    			   			 	  		 						 				//hellobig_tq