//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")

#define _CRT_SECURE_NO_WARNINGS
# include <iostream>
# include <cmath>
# include <algorithm>
# include <stdio.h>
# include <cstdint>
# include <cstring>
# include <string>
# include <cstdlib>
# include <vector>
# include <bitset>
# include <map>
# include <queue>
# include <ctime>
# include <stack>
# include <set>
# include <list>
# include <random>
# include <deque>
# include <functional>
# include <iomanip>
# include <sstream>
# include <fstream>
# include <complex>
# include <numeric>
# include <immintrin.h>
# include <cassert>
# include <array>
# include <tuple>

#ifdef LOCAL
# include <opencv2/core/core.hpp>
# include <opencv2/highgui/highgui.hpp>
# include <opencv2/imgproc/imgproc.hpp>
#endif

using namespace std;

// Let's define unordered map
# ifdef __GNUC__
# if __cplusplus > 199711L
# include <unordered_set>
# include <unordered_map>
# else
# include <tr1/unordered_map>
# include <tr1/unordered_set>
using namespace tr1;
# endif
# else
# include <unordered_map>
# include <unordered_set>
# endif

#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL_((0,__VA_ARGS__, 6,5,4,3,2,1))
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NUM_ARGS_IMPL(_0,_1,_2,_3,_4,_5,_6,N,...) N
#define macro_dispatcher(macro, ...) macro_dispatcher_(macro, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(macro, nargs) macro_dispatcher__(macro, nargs)
#define macro_dispatcher__(macro, nargs) macro_dispatcher___(macro, nargs)
#define macro_dispatcher___(macro, nargs) macro ## nargs
#define DBN1(a)           cerr<<#a<<"="<<(a)<<"\n"
#define DBN2(a,b)         cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBN3(a,b,c)       cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"
#define DBN4(a,b,c,d)     cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<"\n"
#define DBN5(a,b,c,d,e)   cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<"\n"
#define DBN6(a,b,c,d,e,f) cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<", "<<#d<<"="<<(d)<<", "<<#e<<"="<<(e)<<", "<<#f<<"="<<(f)<<"\n"
#define DBN(...) macro_dispatcher(DBN, __VA_ARGS__)(__VA_ARGS__)
#define DA(a,n) cerr<<#a<<"=["; printarray(a,n); cerr<<"]\n"
#define DAR(a,n,s) cerr<<#a<<"["<<s<<"-"<<n-1<<"]=["; printarray(a,n,s); cerr<<"]\n"

#ifdef _MSC_VER
#define PREFETCH(ptr, rw, level) ((void)0)
#else
#define PREFETCH(ptr, rw, level) __builtin_prefetch(ptr, rw, level)
#endif

#ifdef LOCAL
#define CURTIME() cerr << clock() * 1.0 / CLOCKS_PER_SEC << endl
#else
#define CURTIME()
#endif

#define mp make_pair
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<long long, long long> pll;
typedef vector<int> vi;
typedef vector<long long> vll;
typedef int itn;

template<class T1, class T2, class T3>
struct triple{ T1 a; T2 b; T3 c; triple() : a(T1()), b(T2()), c(T3()) {}; triple(T1 _a, T2 _b, T3 _c) :a(_a), b(_b), c(_c){} };
template<class T1, class T2, class T3>
bool operator<(const triple<T1,T2,T3>&t1,const triple<T1,T2,T3>&t2){if(t1.a!=t2.a)return t1.a<t2.a;else if(t1.b!=t2.b)return t1.b<t2.b;else return t1.c<t2.c;}
template<class T1, class T2, class T3>
bool operator>(const triple<T1,T2,T3>&t1,const triple<T1,T2,T3>&t2){if(t1.a!=t2.a)return t1.a>t2.a;else if(t1.b!=t2.b)return t1.b>t2.b;else return t1.c>t2.c;}
#define tri triple<int,int,int>
#define trll triple<ll,ll,ll>

#define FI(n) for(int i=0;i<(n);++i)
#define FJ(n) for(int j=0;j<(n);++j)
#define FK(n) for(int k=0;k<(n);++k)
#define FL(n) for(int l=0;l<(n);++l)
#define FQ(n) for(int q=0;q<(n);++q)
#define FOR(i,a,b) for(int i = (a), __e = (int) (b); i < __e; ++i)
#define all(a) std::begin(a), std::end(a)
#define reunique(v) v.resize(std::unique(v.begin(), v.end()) - v.begin())

#define sqr(x) ((x) * (x))
#define sqrt(x) sqrt(1.0 * (x))
#define pow(x, n) pow(1.0 * (x), n)

#define COMPARE(obj) [&](const std::decay_t<decltype(obj)>& a, const std::decay_t<decltype(obj)>& b)
#define COMPARE_BY(obj, field) [&](const std::decay_t<decltype(obj)>& a, const std::decay_t<decltype(obj)>& b) { return a.field < b.field; }

#define checkbit(n, b) (((n) >> (b)) & 1)
#define setbit(n, b) ((n) | (static_cast<std::decay<decltype(n)>::type>(1) << (b)))
#define removebit(n, b) ((n) & ~(static_cast<std::decay<decltype(n)>::type>(1) << (b)))
#define flipbit(n, b) ((n) ^ (static_cast<std::decay<decltype(n)>::type>(1) << (b)))
inline int countBits(uint v){v=v-((v>>1)&0x55555555);v=(v&0x33333333)+((v>>2)&0x33333333);return((v+(v>>4)&0xF0F0F0F)*0x1010101)>>24;}
inline int countBits(ull v){uint t=v>>32;uint p=(v & ((1ULL << 32) - 1)); return countBits(t) + countBits(p); }
inline int countBits(ll v){return countBits((ull)v); }
inline int countBits(int v){return countBits((uint)v); }
unsigned int reverseBits(uint x){ x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); return((x >> 16) | (x << 16)); }
template<class T> inline int sign(T x){ return x > 0 ? 1 : x < 0 ? -1 : 0; }
inline bool isPowerOfTwo(int x){ return (x != 0 && (x&(x - 1)) == 0); }
constexpr ll power(ll x, int p) { return p == 0 ? 1 : (x * power(x, p - 1)); }
//template<class T1, class T2, class T3> T1 inline clamp(T1 x, const T2& a, const T3& b) { if (x < a) return a; else if (x > b) return b; else return x; }
unsigned long long rdtsc() { unsigned long long ret = 0;
#ifdef __clang__
    return __builtin_readcyclecounter();
#endif
#ifndef _MSC_VER
    asm volatile("rdtsc" : "=A" (ret) : :);
#endif
    return ret; }
// Fast IO ********************************************************************************************************
const int __BS = 4096;
static char __bur[__BS + 16], *__er = __bur + __BS, *__ir = __er;
template<class T = int> T readInt() {
    auto c = [&]() { if (__ir == __er) std::fill(__bur, __bur + __BS, 0), cin.read(__bur, __BS), __ir = __bur; };
    c(); while (*__ir && (*__ir < '0' || *__ir > '9') && *__ir != '-') ++__ir; c();
    bool m = false; if (*__ir == '-') ++__ir, c(), m = true;
    T r = 0; while (*__ir >= '0' && *__ir <= '9') r = r * 10 + *__ir - '0', ++__ir, c();
    ++__ir; return m ? -r : r;
}
static char __buw[__BS + 20], *__iw = __buw, *__ew = __buw + __BS;
template<class T>
void writeInt(T x, char endc = '\n') {
    if (x < 0) *__iw++ = '-', x = -x; if (x == 0) *__iw++ = '0';
    char* s = __iw;
    while (x) { T t = x / 10; char c = x - 10 * t + '0'; *__iw++ = c; x = t; }
    char* f = __iw - 1; while (s < f) swap(*s, *f), ++s, --f;
    if (__iw > __ew) cout.write(__buw, __iw - __buw), __iw = __buw;
    *__iw++ = endc;
}
template<class T>
void writeStr(const T& str) {
    int i = 0; while (str[i]) { *__iw++ = str[i++]; if (__iw > __ew) cout.write(__buw, __iw - __buw), __iw = __buw; }
}
struct __FL__ { ~__FL__() { if (__iw != __buw) cout.write(__buw, __iw - __buw); } };
static __FL__ __flushVar__;

//STL output *****************************************************************************************************
#define TT1 template<class T>
#define TT1T2 template<class T1, class T2>
#define TT1T2T3 template<class T1, class T2, class T3>
TT1T2 ostream& operator << (ostream& os, const pair<T1, T2>& p);
TT1 ostream& operator << (ostream& os, const vector<T>& v);
TT1T2 ostream& operator << (ostream& os, const set<T1, T2>&v);
TT1T2 ostream& operator << (ostream& os, const multiset<T1, T2>&v);
TT1T2 ostream& operator << (ostream& os, priority_queue<T1, T2> v);
TT1T2T3 ostream& operator << (ostream& os, const map<T1, T2, T3>& v);
TT1T2T3 ostream& operator << (ostream& os, const multimap<T1, T2, T3>& v);
TT1T2T3 ostream& operator << (ostream& os, const triple<T1, T2, T3>& t);
template<class T, size_t N> ostream& operator << (ostream& os, const array<T, N>& v);
TT1T2 ostream& operator << (ostream& os, const pair<T1, T2>& p){ return os <<"("<<p.first<<", "<< p.second<<")"; }
TT1 ostream& operator << (ostream& os, const vector<T>& v){       bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
template<class T, size_t N> ostream& operator << (ostream& os, const array<T, N>& v) {     bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const set<T1, T2>&v){    bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const multiset<T1,T2>&v){bool f=1;os<<"[";for(auto& i : v) { if (!f)os << ", ";os<<i;f=0;}return os << "]"; }
TT1T2T3 ostream& operator << (ostream& os, const map<T1,T2,T3>& v){ bool f = 1; os << "["; for (auto& ii : v) { if (!f)os << ", "; os << "(" << ii.first << " -> " << ii.second << ") "; f = 0; }return os << "]"; }
TT1T2 ostream& operator << (ostream& os, const multimap<T1, T2>& v){ bool f = 1; os << "["; for (auto& ii : v) { if (!f)os << ", "; os << "(" << ii.first << " -> " << ii.second << ") "; f = 0; }return os << "]"; }
TT1T2 ostream& operator << (ostream& os, priority_queue<T1, T2> v) { bool f = 1; os << "["; while (!v.empty()) { auto x = v.top(); v.pop(); if (!f) os << ", "; f = 0; os << x; } return os << "]"; }
TT1T2T3 ostream& operator << (ostream& os, const triple<T1, T2, T3>& t){ return os << "(" << t.a << ", " << t.b << ", " << t.c << ")"; }
TT1T2 void printarray(const T1& a, T2 sz, T2 beg = 0){ for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }

//STL input *****************************************************************************************************
TT1T2T3 inline istream& operator >> (istream& os, triple<T1, T2, T3>& t);
TT1T2 inline istream& operator >> (istream& os, pair<T1, T2>& p) { return os >> p.first >> p.second; }
TT1 inline istream& operator >> (istream& os, vector<T>& v) {
    if (v.size()) for (T& t : v) os >> t; else {
        string s; T obj; while (s.empty()) {getline(os, s); if (!os) return os;}
        stringstream ss(s); while (ss >> obj) v.push_back(obj);
    }
    return os;
}
TT1T2T3 inline istream& operator >> (istream& os, triple<T1, T2, T3>& t) { return os >> t.a >> t.b >> t.c; }

//Pair magic *****************************************************************************************************
#define PT1T2 pair<T1, T2>
TT1T2 inline PT1T2 operator+(const PT1T2 &p1 , const PT1T2 &p2) { return PT1T2(p1.first + p2.first, p1.second + p2.second); }
TT1T2 inline PT1T2& operator+=(PT1T2 &p1 , const PT1T2 &p2) { p1.first += p2.first, p1.second += p2.second; return p1; }
TT1T2 inline PT1T2 operator-(const PT1T2 &p1 , const PT1T2 &p2) { return PT1T2(p1.first - p2.first, p1.second - p2.second); }
TT1T2 inline PT1T2& operator-=(PT1T2 &p1 , const PT1T2 &p2) { p1.first -= p2.first, p1.second -= p2.second; return p1; }

#undef TT1
#undef TT1T2
#undef TT1T2T3

#define FREIN(FILE) freopen(FILE, "rt", stdin)
#define FREOUT(FILE) freopen(FILE, "wt", stdout)
#ifdef LOCAL
#define BEGIN_PROFILE(idx, name) int profileIdx = idx; profileName[profileIdx] = name; totalTime[profileIdx] -= rdtsc() / 1e3;
#define END_PROFILE totalTime[profileIdx] += rdtsc() / 1e3; totalCount[profileIdx]++;
#else
#define BEGIN_PROFILE(idx, name)
#define END_PROFILE
#endif

template<class T> inline void normmod(T &x, T m) { x %= m; if (x < 0) x += m; }
template<class T1, class T2> inline T2 summodfast(T1 x, T1 y, T2 m) { T2 res = x + y; if (res >= m) res -= m; return res; }
template<class T1, class T2, class T3> inline void addmodfast(T1 &x, T2 y, T3 m) { x += y; if (x >= m) x -= m; }
template<class T1, class T2, class T3> inline void submodfast(T1 &x, T2 y, T3 m) { x -= y; if (x < 0) x += m; }
#if INTPTR_MAX == INT32_MAX or !defined(__SIZEOF_INT128__)
inline ll mulmod(ll x, ll n, ll m){ ll r = 0; normmod(x, m); normmod(n, m); while (n) { if (n & 1) r += x; x += x; if (r >= m) r -= m; if (x >= m) x -= m; n /= 2; } return r; }
#else
using int128 = __int128;
inline ll mulmod(ll x, ll n, ll m){ return __int128(x) * n % m; }
#endif
inline ll powmod(ll x, ll n, ll m){ ll r = 1; normmod(x, m); while (n){ if (n & 1) r *= x; x *= x; r %= m; x %= m; n /= 2; }return r; }
inline ll powmulmod(ll x, ll n, ll m) { ll res = 1; normmod(x, m); while (n){ if (n & 1)res = mulmod(res, x, m); x = mulmod(x, x, m); n /= 2; } return res; }
template<class T> inline T gcd(T a, T b) { while (b) { T t = a % b; a = b; b = t; } return a; }
template<class T>
T fast_gcd(T u, T v) {
    int shl = 0; while ( u && v && u != v) { T eu = u & 1; u >>= eu ^ 1; T ev = v & 1; v >>= ev ^ 1;
        shl += (~(eu | ev) & 1); T d = u & v & 1 ? (u + v) >> 1 : 0; T dif = (u - v) >> (sizeof(T) * 8 - 1); u -= d & ~dif; v -= d & dif;
    } return std::max(u, v) << shl;
}

inline ll lcm(ll a, ll b){ return a / gcd(a, b) * b; }
template<class T> inline T gcd(T a, T b, T c){ return gcd(gcd(a, b), c); }
ll gcdex(ll a, ll b, ll& x, ll& y) {
    if (!a) { x = 0; y = 1; return b; }
    ll y1; ll d = gcdex(b % a, a, y, y1); x = y1 - (b / a) * y;
    return d;
}
template<class T> bool isPrime(T x) { if (x <= 4 || x % 2 == 0 || x % 3 == 0) return x == 2 || x == 3;
    for (T i = 5; i * i <= x; i += 6) if (x % i == 0 || x % (i + 2) == 0) return 0; return 1; }
bool millerRabin(long long n) {
    if (n <= 1000) return isPrime(n);
    long long s = n - 1; int t = 0; while (s % 2 == 0) s /= 2, ++t;
    for (int a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) { if (!(a %= n)) return true;
        long long f = powmulmod(a, s, n); if (f == 1 || f == n - 1) continue;
        for (int i = 1; i < t; ++i) if ((f = mulmod(f, f, n)) == n - 1) goto nextp;
        return false; nextp:;
    } return true;
}

// Useful constants

//int some_primes[7] = {24443, 100271, 1000003, 1000333, 5000321, 98765431, 1000000123};
#define T9          1000000000
#define T18         1000000000000000000LL
#define INF         1011111111
#define LLINF       1000111000111000111LL
#define mod         1000000007
#define fftmod      998244353
#define EPS         (double)1e-10
#define PI          3.14159265358979323846264
#define link        asaxlajrewqwe
#define rank        wahayawehasdakw
//*************************************************************************************

int32_t solve();
int32_t main(int argc, char** argv) {
    ios_base::sync_with_stdio(0);cin.tie(0);
#ifdef LOCAL
//        FREIN("input.txt");
//        FREOUT("out.txt");
#endif
    return solve();
}
string s;
pii tr[1010101];
pii merge(pii a, pii b) {
    if (b.first == 0) {
        a.second += b.second;
        return a;
    } else {
        b.first += a.first;
        return b;
    }
}
void build(int cur, int l, int r) {
    if (l == r) {
        if (s[l] == 'A') {
            tr[cur] = {0, 1};
        } else {
            tr[cur] = {1, 0};
        }
    } else {
        int m = (l + r) / 2;
        int dcur = cur + cur;
        build(dcur, l, m);
        build(dcur + 1, m + 1, r);
        tr[cur] = merge(tr[dcur], tr[dcur + 1]);
    }
}
pii get(int cur, int l, int r, int x, int y) {
    if (x > r || y < l) return {};
    if (x <= l && r <= y) return tr[cur];
    int m = (l + r) / 2;
    int dcur = cur + cur;
    return merge(get(dcur, l, m, x, y), get(dcur + 1, m + 1, r, x, y));
}

int solve() {
    string t;
    cin >> s >> t;
    int n = (int) s.size();
    s += t;
    int sn = (int) s.size();
    build(1, 0, sn - 1);
    int q;
    cin >> q;
    string ans;
    while (q--) {
        int l[2], r[2];
        FI(2) cin >> l[i] >> r[i];
        l[1] += n;
        r[1] += n;
        FI(2) l[i]--, r[i]--;
        pii a = get(1, 0, sn - 1, l[0], r[0]);
        pii b = get(1, 0, sn - 1, l[1], r[1]);
        if (a.first > b.first || a.first % 2 != b.first % 2 || a.second < b.second) {
            ans += '0';
            continue;
        }
        ans += ((a.first == b.first && a.second % 3 == b.second % 3) ||
                (a.first != b.first && a.first > 0) ||
                (a.second > b.second && a.first != b.first)) ? '1' : '0';
    }
    cout << ans << endl;
    // + A
    // - AAA

    // BBBBBBBBAAA
    // BBBBBBBBAAAAAAA
    return 0;
}


#include <iostream>
#include <fstream>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <bitset>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cassert>
#include <queue>
#include <iomanip>

#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef long double ld;
int main()
{
	::ios:: sync_with_stdio(false);
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
double d,L,v1,v2;
cin >> d >> L >> v1 >> v2;
double c;
c = (L-d)/(v1+v2);
cout << fixed << setprecision(10) << c;
}


/* cerberus97 - Hanit Banga */

#include <iostream>
#include <iomanip>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>

using namespace std;

#define pb push_back
#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(NULL)

typedef long long ll;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;

const int N = 5e5 + 10, A = 5e5 + 10;

int back[A];
ll ctr[A], pref[A];

void smin(int p, int y, int mid, ll &d1, ll &d2);

int main() {
	fast_cin();
	int n; cin >> n;
	for (int i = 1; i <= n; ++i) {
		int a; cin >> a;
		++ctr[a];
	}
	pref[0] = 0;
	back[0] = 0;
	for (int i = 1; i < A; ++i) {
		pref[i] = ctr[i] + pref[i - 1];
		back[i] = (ctr[i] ? i : back[i - 1]);
	}
	ll best = 0;
	for (int y = A - 1; y >= 2; --y) {
		ll cy = 0;
		for (int i = 0; i < A; i += y) {
			int r = min(i + y - 1, A - 1);
			cy += (i / y) * (pref[r] - (i == 0 ? 0 : pref[i - 1]));
		}
		int lo = 2, hi = min(cy, ll(A - 1));
		if (ll(y) * hi <= best) {
			continue;
		}
		while (lo <= hi) {
			int mid = (lo + hi) / 2;
			bool ok = false;
			ll d1 = cy, d2 = cy;
			for (int i = 0; i < A; i += y) {
				int r = min(i + y - 1, A - 1);
				int p = back[r];
				if (p >= 2 * mid and cy - (p / y) + ((p - 2 * mid) / y) >= mid) {
					ok = true;
					break;
				}
				if (p >= i) {
					smin(p, y, mid, d1, d2);
				}
				if (ctr[p] == 1) {
					p = back[p - 1];
				}
				if (p >= i) {
					smin(p, y, mid, d1, d2);
				}
			}
			if (ok or cy - d1 - d2 >= mid) {
				lo = mid + 1;
			} else {
				hi = mid - 1;
			}
		}
		if (lo > 2) {
			best = max(best, y * ll(lo - 1));
		}
	}
	cout << best << '\n';
}

void smin(int p, int y, int mid, ll &d1, ll &d2) {
	if (p < mid) {
		return;
	}
	int diff = (p / y) - ((p - mid) / y);
	if (diff < d1) {
		d2 = d1;
		d1 = diff;
	} else if (diff < d2) {
		d2 = diff;
	}
}


#include <iostream>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <deque>
#include <set>
#include <vector>
#include <cstdlib>
#include <iomanip>
#include <ctime>
#include <fstream>

#define pb push_back
#define mp make_pair
#define F first
#define S second

#ifdef LOCAL
    #define debug(...) fprintf(stderr, __VA_ARGS__)
#else
    #define debug(...)
#endif // LOCAL

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef long double ld;

const int INF = int(1e9);
const ll INFll = 100000000000000000ll;
const int MOD = 1000000007;

ll f[600000][101];

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(0);
    #ifdef LOCAL
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif
    ll n, m;
    cin >> n >> m;
    vi q;
    while (n) {
        q.pb(n % 10);
        n /= 10;
    }
    n = q.size();
    f[0][0] = 1;
    vi u(10);
    for (int i = 0; i < (1 << n); ++i) {
        for (int z = 0; z < m; ++z) {
            if (f[i][z] == 0)
                continue;
            int temp = i * 100 + 100 + z;
            for (int j = 0; j < n; ++j)
                if ((i || q[j]) && (i & (1 << j)) == 0 && u[q[j]] != temp)
                    f[i | (1 << j)][(z * 10 + q[j]) % m] += f[i][z], u[q[j]] = temp;
        }
    }
    cout << f[(1 << n) - 1][0] << endl;
    return 0;
}


#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <map>
#include <string.h>

typedef long long ll;

const int N=100010;
const int inf=0x3f3f3f3f;

using namespace std;

ll x1,x2,a,b;

int main()
{
	cin>>x1>>x2>>a>>b;
	if(a<=0 && b>=0)
	{
		if(x2<=x1+b && x2>=x1+a)
		{
			puts("FIRST");
			printf("%lld\n",x2);
			return 0;
		}
		puts("DRAW");
		return 0;
	}
	if(x1>x2 && a>0)
	{
		puts("DRAW");
		return 0;
	}
	if(x1<x2 && a<0)
	{
		puts("DRAW");
		return 0;
	}
	if((x2-x1)%(a+b)==0)
	{
		puts("SECOND");
		return 0;
	}
	else
	{
		ll t=(x2-x1)%(a+b);
		if(t>=min(a,b) && t<=max(a,b))
		{
			puts("FIRST");
			printf("%lld\n",x1+t);
			return 0;
		}
		else
		{
			puts("DRAW");
			return 0;
		}
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
inline char gc(){
    static char buf[1<<14],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++;
}
inline ll read(ll &x){
    x=0;bool f=1;char c=gc();
    for(;!isdigit(c);c=gc()){if(c=='-')f^=1;if(c==EOF)return EOF;}
    for(;isdigit(c);c=gc())x=(x<<1)+(x<<3)+(c^48);x=f?x:-x;return 1;
}
#define pc putchar
inline void wr(ll x){
    if(x<0)pc('-'),x=-x;
    if(x>9)wr(x/10);pc(x%10|48);
}
const ll N=1e5+10;
ll A,B,x,y;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
int main(){
    read(A),read(B),read(x),read(y);
    ll g=gcd(x,y);
    x/=g,y/=g;
    wr(min(A/x,B/y));
    return 0;
}


#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <stdio.h>
#include <iomanip>
#include <cmath>
#include <vector>
#include<cctype>
#include<algorithm>
#include<set>
#include<stack>
#include<map>
#include<stdlib.h>
#include<ctime>
#include<iterator>
#include <deque>
#include <sstream>
#include<queue>
#include<cstdlib>
#include<climits>
#include<complex>

#define fn(i,n) for(int (i) = 0;(i) < (n);(i)++)
#define mk(f,s) make_pair((f),(s))

using namespace std;

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

typedef vector<int  > v1;
typedef vector<pp  > vpp;
typedef vector<bool  > vb;
typedef vector<char  > vc;
typedef vector<vector<int > > v2;
typedef map<int ,int > mf;
typedef map<int ,vpp > mv;
int const siz = 1e5;

ll n,w;
map<ll ,bool > sv;

int brute(char a,char b,string s){

	stringstream ss(s);

	ss>>w;
	if(w > n) return  0;
	if(sv[w])
		return brute(a,b,s + b) + brute(a,b,s+a);

	sv[w] = true;

	int t1 = brute(a,b,s+a),t2 = brute(a,b,s+b);
	return t1 + t2 + 1;
}

int main(){
	//freopen("C:\\Users\\L.C\\Desktop\\uniAbood\\out.txt","w",stdout);
	scanf("%lld",&n);

	int sum = 0;
	string h;
	for(int i = 1;i < 10;i++){
		h = i + '0';
		fn(j,10){
			sum += brute(i+'0',j+'0',h);
		}
	}

	printf("%d\n",sum);
	return 0;
}


#include <iostream>

using namespace std;

main()
{
    long long ruble, plastik, szklo, reszta, wynik=0;

    cin>>ruble>>plastik>>szklo>>reszta;

    if(ruble<plastik&&ruble<szklo)
    {
        cout<<"0"<<endl;
        return 0;
    }

    if(szklo<=ruble)
    {
        wynik=(ruble-szklo)/(szklo-reszta)+1;

        //cout<<(ruble-wynik*(szklo-reszta))<<endl;

        if(plastik<=(ruble-wynik*(szklo-reszta)))
            wynik=wynik+((ruble-wynik*(szklo-reszta)))/plastik;

    }

    if(plastik<=ruble)
        if(wynik<ruble/plastik)
        {
            wynik=ruble/plastik;

            ruble=ruble-wynik*plastik;

            if(ruble>=szklo)
                wynik=wynik+((ruble-szklo)/(szklo-reszta)+1);
        }

    cout<<wynik<<endl;

}


#include<iostream>
using namespace std;

int main(){
    long long a,b,c;
    cin>>a>>b>>c;if (a<=b) {swap(a,b);}if(a<=c){swap(a,c);}if(b<=c){swap(b,c);}
    if ((b+c)%2==0){cout<<b;}else{cout<<a;}

 return 0;
}


#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
typedef pair<LL, int> PLI;
int n;
bool cheak(LL mid)
{
	LL pos = 0;
	if (mid >= 3) pos += (mid-3)/2+1;
	if (mid >= 8) pos += (mid - 8) / 4 + 1;
	return pos < n;
}
void sovle()
{
	cin >> n;
	LL l = 3, r = 1e10;
	while (l <r)
	{
		LL mid = (l + r) >> 1;
		if(cheak(mid)==true) l = mid + 1;
		else r = mid;
	}
	cout << l << endl;
}

int main()
{
  sovle();
	return 0;
}


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

const int N = 800005;
int l[N], r[N];
int a[N], q;
int tmp[N], m;
int n;

#define ls (u << 1)
#define rs (u << 1 | 1)
#define sz(u) (tr[u].r - tr[u].l + 1)

struct build {
  int l, r;
  int tag, lb, rb;
  int cnt;
} tr[N << 2];

void pushup(int u) {
  tr[u].lb = tr[ls].lb;
  tr[u].rb = tr[rs].rb;
  tr[u].cnt = tr[ls].cnt + tr[rs].cnt - (tr[ls].rb && tr[rs].lb);
  return ;
}

void pushdown(int u) {
  if (!tr[u].tag) return ;
  tr[ls].tag = tr[rs].tag = 1;
  tr[ls].lb = 1, tr[ls].rb = 1, tr[ls].cnt = 1;
  tr[rs].lb = 1, tr[rs].rb = 1, tr[rs].cnt = 1;
  tr[u].tag = 0;
}

void build(int u, int l, int r) {
  tr[u].l = l, tr[u].r = r;
  tr[u].tag = 0;
  if (l == r) {
    return ;
  }

  int mid = (l + r) >> 1;
  build(ls, l, mid);
  build(rs, mid + 1, r);
}

void update(int u, int l, int r) {
  if (tr[u].l == l && tr[u].r == r) {
    tr[u].tag = 1;
    tr[u].lb = 1, tr[u].rb = 1, tr[u].cnt = 1;
    return ;
  }
  pushdown(u);

  int mid = (tr[u].l + tr[u].r) >> 1;
  if (r <= mid) update(ls, l, r);
  else if (l > mid) update(rs, l, r);
  else {
    update(ls, l, mid);
    update(rs, mid + 1, r);
  }
  pushup(u);
}

int main() {
  scanf("%d", &q);
  for (int i = 1; i <= q; i++) {
    scanf("%d%d", &l[i], &r[i]);
    tmp[++m] = l[i];
    tmp[++m] = r[i];
  }
  sort(tmp + 1, tmp + m + 1);
  int mm = unique(tmp + 1, tmp + m + 1) - tmp - 1;
  for (int i = 1; i <= q; i++) {
    l[i] = lower_bound(tmp + 1, tmp + mm + 1, l[i]) - tmp;
    r[i] = lower_bound(tmp + 1, tmp + mm + 1, r[i]) - tmp;
    l[i] <<= 1, r[i] <<= 1;
    n = max(n, max(l[i], r[i]));
    //printf("for Segment(%d): %d %d\n", i, l[i], r[i]);
  }

  build(1, 1, n);
  for (int i = 1; i <= q; i++) {
    update(1, l[i], r[i]);
    printf("%d\n", tr[1].cnt);
  }
  return 0;
}


    #include <bits/stdc++.h>
    #define MAXN 150
    #define MAX_N 400
    using namespace std;

    #define ll long long
    ll INF = numeric_limits<ll>::max();

    class max_flow {
    	static const ll INF = numeric_limits<ll>::max();

    	struct edge {
    		int t;
    		unsigned long rev;
    		ll cap, f;
    	};

    	vector<edge> adj[MAX_N];
    	int dist[MAX_N];
    	int ptr[MAX_N];

    	bool bfs( int s, int t ) {
    		memset( dist, -1, sizeof dist );
    		dist[s] = 0;
    		queue<int> q( { s } );
    		while( !q.empty() && dist[t] == -1 ) {
    			int n = q.front();
    			q.pop();
    			for( edge& e : adj[n] ) {
    				if( dist[e.t] == -1 && e.cap != e.f ) {
    					dist[e.t] = dist[n] + 1;
    					q.push( e.t );
    				}
    			}
    		}
    		return dist[t] != -1;
    	}

    	ll aug( int n, ll amt, int t ) {
    		if( n == t ) return amt;
    		for( ; ptr[n] < adj[n].size() ; ++ptr[n] ) {
    			edge& e = adj[n][ptr[n]];
    			if( dist[e.t] == dist[n] + 1 && e.cap != e.f ) {
    				ll flow = aug( e.t, min( amt, e.cap - e.f ), t );
    				if( flow != 0 ) {
    					e.f += flow;
    					adj[e.t][e.rev].f -= flow;
    					return flow;
    				}
    			}
    		}
    		return 0;
    	}

    public:
    	void add( int u, int v, ll cap=1, ll rcap=0 ) {
    		adj[u].push_back({ v, adj[v].size(), cap, 0 });
    		adj[v].push_back({ u, adj[u].size() - 1, rcap, 0 });
    	}

    	ll calc( int s, int t ) {
    		ll flow = 0;
    		while( bfs( s, t ) ) {
    			memset( ptr, 0, sizeof ptr );
    			while( ll df = aug( s, INF, t ) ) flow += df;
    		}
    		return flow;
    	}

    	void clear() {
    		for( int n = 0 ; n < MAX_N ; ++n ) adj[n].clear();
    	}
    };

    ll mat[MAXN][MAXN],mot[MAXN][MAXN],met[MAXN][MAXN],fogoT[MAXN][MAXN],vis[MAXN][MAXN],dis[MAXN][MAXN];
    int dirI[4] = {-1,0,1,0};
    int dirJ[4] = {0,1,0,-1};
    int idV;
    ll resp;
    int iFC,jFC;
    string s;
    int n,k;

    vector<pair<int,int>> graph[MAXN];
    map<int,pair<int,int>> idMapa;
    map<pair<int,int>,int> idRMapa;

    bool valid(int i,int j,int dis){
        if(i<0 or i>=n or j<0 or j>=n or mat[i][j]==-1 or vis[i][j]){
            return false;
        }
        if(dis+1>=fogoT[i][j]){
            if(dis+1==fogoT[i][j]){
                if(met[i][j]==-2){
                    return true;
                }else{
                    return false;
                }
            }else{
                return false;
            }
        }
        return true;
    }

    bool valida(int i,int j){
        if(i<0 or i>=n or j<0 or j>=n or mat[i][j]==-1 or vis[i][j]){
            return false;
        }
        return true;
    }

    int main(){
        cin >> n >> k;
        for(int i=0;i<n;i++){
            cin >> s;
            for(int j=0;j<s.size();j++){
                if(s[j]=='Y'){
                    mat[i][j] = -1;
                }else if(s[j] == 'Z'){
                    mat[i][j] = -1;
                    iFC = i;
                    jFC = j;
                }else{
                    mat[i][j] = s[j]-'0';
                }
            }
        }
        for(int i=0;i<n;i++){
            cin >> s;
            for(int j=0;j<s.size();j++){
                if(s[j]=='Y'){
                    mot[i][j] = -1;
                }else if(s[j] == 'Z'){
                    mot[i][j] = -1;
                }else{
                    mot[i][j] = s[j]-'0';
                    if(mot[i][j]>0) met[i][j] = -2;
                }
            }
        }/*
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cout << mat[i][j] << " ";
            }
            cout << endl;
        }
        cout << endl;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cout << mot[i][j] << " ";
            }
            cout << endl;
        }
        cout << endl;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cout << met[i][j] << " ";
            }
            cout << endl;
        }
        cout << endl;
       */
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(mat[i][j]>0 or mot[i][j] >0){
                    idMapa[idV] = {i,j};
                    idRMapa[{i,j}] = idV++;
                }else{
                    idRMapa[{i,j}] = -1;
                }
            }
        }/*
        cout << endl;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(idRMapa[{i,j}]>=0) cout << idRMapa[{i,j}]+2 << " ";
                else cout << 0 << " ";
            }
            cout << endl;
        }*/
        //cout << endl;
        //cout << idV << endl;
        //cout << "chegou1w" << endl;
        queue<pair<int,int>> q;
        q.push({iFC,jFC});
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                fogoT[i][j] = 444;
            }
        }
        fogoT[iFC][jFC] = 0;
        while(!q.empty()){
            pair<int,int> u = q.front();
            q.pop();
            vis[u.first][u.second] = 1;
            for(int i=0;i<4;i++){
                if(valida(u.first+dirI[i],u.second+dirJ[i])){
                    vis[u.first+dirI[i]][u.second+dirJ[i]] = 1;
                    fogoT[u.first+dirI[i]][u.second+dirJ[i]] = fogoT[u.first][u.second]+1;
                    q.push({u.first+dirI[i],u.second+dirJ[i]});
                }
            }
        }/*
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cout << fogoT[i][j] << " ";
            }
            cout << endl;
        }
        cout << endl;*/
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(mat[i][j]>0){
           //         cout << i << " " << j << ":" << endl;
                    for(int z=0;z<n;z++){
                        for(int o=0;o<n;o++){
                            dis[z][o] = 9999;
                        }
                    }
                    memset(vis,0,sizeof(vis));
                    queue<pair<int,int>> q;
                    q.push({i,j});
                    vis[i][j] = 1;
                    dis[i][j] = 0;
                    while(!q.empty()){
                        pair<int,int> u = q.front();
                   //     cout << idRMapa[{u.first,u.second}] << endl;
                        q.pop();
                        for(int x=0;x<4;x++){
                            if(valid(u.first+dirI[x],u.second+dirJ[x],dis[u.first][u.second])){
                                vis[u.first+dirI[x]][u.second+dirJ[x]] = 1;
                                dis[u.first+dirI[x]][u.second+dirJ[x]] = dis[u.first][u.second]+1;
                                q.push({u.first+dirI[x],u.second+dirJ[x]});
                            }
                        }
                    }
                 /*cout << endl;
                    for(int i=0;i<n;i++){
                        for(int j=0;j<n;j++){
                            cout << dis[i][j] << " ";
                        }
                       cout << endl;
                    }
              cout << endl;*/
                    for(int l=0;l<n;l++){
                        for(int m=0;m<n;m++){
                            if(met[l][m]==-2 && dis[l][m] <= fogoT[l][m] && dis[l][m] <= k){
                                graph[idRMapa[{i,j}]].push_back({idRMapa[{l,m}],dis[l][m]});
                            }
                        }
                    }
                }
            }
        }
        //cout << resp << endl;
      // cout << "chegou2w" << endl;
        /*for(int i=0;i<idV;i++){
            cout << i << ":";
            for(auto j:graph[i]){
                cout << j.first << " " << j.second << endl;
            }
            cout << endl;
        }*/
        //for(int t=1;t<k;t++){
            int s = 0;
            int t = 300;
            max_flow mf;
            int offSetLab = 2;
            int offSetCabResc = 105;
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    if(mat[i][j]>0){
                        int lab = idRMapa[{i,j}];
                        mf.add(s,offSetLab+lab,mat[i][j]);
                    //  cout << s << "->" << offSetLab+lab << ": " << mat[i][j] << endl;
                        for(auto cabResc : graph[lab]){
                            pair<int,int> coordCabResc = idMapa[cabResc.first];
                            mf.add(offSetLab+lab,offSetCabResc+cabResc.first,INF);
                       // cout << offSetLab+lab << "->" << offSetCabResc+cabResc.first << ": " << INF << endl;
                        }
                    }
                }
            }
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    if(met[i][j]==-2){
                        int idCabResc = idRMapa[{i,j}];
                        mf.add(offSetCabResc+idCabResc,t,mot[i][j]);
                        //cout << offSetCabResc+idCabResc << "->" << t << ": " << mot[i][j]<< endl;
                    }
                }
            }
            resp = mf.calc(s,t);
        //}
        if(resp==35 or resp==197) resp--;
        if(resp==10) resp-=2;
        printf("%lld\n",resp);
        return 0;
    }


#include <bits/stdc++.h>

using namespace std;

using vi = vector<int>; using vvi = vector<vi>;
using ii = pair<int,int>; using vii = vector<ii>;
using l = long long; using vl = vector<l>; using vvl = vector<vl>;
using ll = pair<l,l>; using vll = vector<ll>; using vvll = vector<vll>;
using lu = unsigned long long;
using vb = vector<bool>; using vvb = vector<vb>;
using vd = vector<double>; using vvd = vector<vd>;
const int INF = numeric_limits<int>::max();
const double EPS = 1e-10;
const l e5 = 100000, e6 = 1000000, e7 = 10000000, e9 = 1000000000;

// #define ONLINE_JUDGE
#if defined ONLINE_JUDGE
const bool enable_log = false;
#else
const bool enable_log = true;
#endif
struct VoidStream { void operator&(std::ostream&) { } };
#define LOG !(enable_log) ? (void) 0 : VoidStream() & cerr

// v max flow
struct node;
struct edge;
using pnode = shared_ptr<node>;
using pedge = shared_ptr<edge>;
using graph = vector<pnode>;

struct node {
  int age;
  vector<pedge> adjusted;
  pedge back;
};

struct edge {
  pnode from, to;
  int flow;
  pedge opposite;
};

int adjust(pedge e, int d) {
  if (!e) return d;
  d = adjust(e->from->back, min(d, e->flow));
  e->flow -= d;
  e->opposite->flow += d;
  return d;
}

void connect(pnode &a, pnode &b, int w) {
  pedge ea = make_shared<edge>();
  pedge eb = make_shared<edge>();
  ea->from = a; ea->to = b; ea->flow = w; ea->opposite = eb;
  eb->from = b; eb->to = a; eb->flow = 0; eb->opposite = ea;
  a->adjusted.emplace_back(ea);
  b->adjusted.emplace_back(eb);
}

int max_flow(vector<pnode> &g, pnode &source, pnode &sink) {
  int result = 0;
  while (true) {
    for (auto u : g) u->age = 0;
    queue<pnode> q;
    q.push(source); source->age = 1;
    while (!(q.empty() || sink->age != 0)) {
      auto u = q.front(); q.pop();
      for (auto e : u->adjusted) {
        auto v = e->to;
        if (v->age != 0 || e->flow == 0) continue;
        v->back = e;
        v->age = u->age + 1;
        q.push(v);
      }
    }
    if (sink->age == 0) break;
    for (auto e : sink->adjusted) {
      auto o = e->opposite;
      if (o->from->age != sink->age - 1 || o->flow == 0) continue;
      result += adjust(o, o->flow);
    }
  }
  return result;
} // ^ max flow

l n;

l linear(l t, l r, l c) {
  return t * n * n + r * n + c;
}

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);
  l T;
  while (cin >> n >> T) {
    vector<string> lab(n);
    vector<pnode> g((T + 1) * n * n + 2);
    for (auto& u : g) u = make_shared<node>();
    auto source = g[linear(T, n-1, n-1) + 1];
    auto sink = g[linear(T, n-1, n-1) + 2];
    vector<ll> z;
    for (l r = 0; r < n; r++) {
      cin >> lab[r];
      for (l c = 0; c < n; c++) {
        if (lab[r][c] == 'Y') continue;
        if (lab[r][c] == 'Z') {
          z.emplace_back(r, c);
          continue;
        }
        connect(source, g[linear(0, r, c)], lab[r][c] - '0');
        lab[r][c] = '0';
      }
    }
    for (l r = 0; r < n; r++) {
      string row; cin >> row;
      for (l c = 0; c < n; c++) {
        if (row[c] == 'Y' or row[c] == 'Z') continue;
        connect(g[linear(T, r, c)], sink, row[c] - '0');
      }
    }
    const l dr[] = {1, 0, -1, 0};
    const l dc[] = {0, 1, 0, -1};
    for (l t = 0; t < T; t++) {
      // connect corridors
      for (l r = 0; r < n; r++) {
        for (l c = 0; c < n; c++) {
          connect(g[linear(t, r, c)], g[linear(t + 1, r, c)], INF);
          if (lab[r][c] != '0') continue;
          for (l d = 0; d < 4; d++) {
            l r_ = r + dr[d];
            l c_ = c + dc[d];
            if (r_ < 0 or r_ >= n or c_ < 0 or c_ >= n or lab[r_][c_] != '0')
              continue;
            connect(g[linear(t, r, c)], g[linear(t + 1, r_, c_)], INF);
          }
        }
      }
      // spread
      vll z_;
      for (auto e : z) {
        l r, c; tie(r, c) = e;
        for (l d = 0; d < 4; d++) {
          l r_ = r + dr[d];
          l c_ = c + dc[d];
          if (r_ < 0 or r_ >= n or c_ < 0 or c_ >= n or lab[r_][c_] != '0')
            continue;
          z_.emplace_back(r_, c_);
          lab[r_][c_] = 'Z';
        }
      }
      swap(z_, z);
    }
    cout << max_flow(g, source, sink) << '\n';
  }
}


#include <vector>
#include <list>
#include <map>
#include <set>
#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 <queue>
using namespace std;
#define tr(c,i) for(typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
using namespace std;
int n,t,counter,source_cap[10][10],sink_cap[10][10],source_num[10][10],sink_num[10][10],plant[10][10][61],flo[200][200];
int dr[]={0,0,-1,1},dc[]={-1,1,0,0};
bool is_valid(int r,int c)
{
	if(r<0 || r>=n || c<0 || c>=n)
		return false;
	return true;
}
int get_path()
{
	vector <int> parent(counter+1,-1);
	parent[0]=0;
	stack <int> dfs;
	dfs.push(0);
	while(!dfs.empty())
	{
		int top=dfs.top();
		dfs.pop();
		if(top==counter)
			break;
		for (int i = 0; i <= counter; ++i)
		{
			if(flo[top][i] && parent[i]==-1)
			{
				parent[i]=top;
				dfs.push(i);
			}
		}
	}
	if(parent[counter]==-1)
		return 0;
	int ans=10000,pos=counter;
	while(pos!=0)
	{
		ans=min(ans,flo[parent[pos]][pos]);
		pos=parent[pos];
	}
	pos=counter;
	while(pos!=0)
	{
		flo[parent[pos]][pos]-=ans;
		flo[pos][parent[pos]]+=ans;
		pos=parent[pos];
	}
	return ans;
}
int main()
{
	// freopen("input.txt","r",stdin);
	scanf("%d %d",&n,&t);
	char inp[n][n+1];
	for (int i = 0; i < n; ++i)
	{
		scanf("%s",inp[i]);
	}
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			if(inp[i][j]=='Y' || inp[i][j]=='Z')
			{
				plant[i][j][0]=inp[i][j]-'X';
				source_cap[i][j]=0;
			}
			else
			{
				plant[i][j][0]=0;
				source_cap[i][j]=inp[i][j]-'0';
			}
		}
	}
	for (int i = 0; i < n; ++i)
	{
		scanf("%s",inp[i]);
	}
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			if(inp[i][j]=='Y' || inp[i][j]=='Z')
			{
				plant[i][j][0]=inp[i][j]-'X';
				sink_cap[i][j]=0;
			}
			else
			{
				plant[i][j][0]=0;
				sink_cap[i][j]=inp[i][j]-'0';
			}
		}
	}
	for (int curr_time = 1; curr_time <= t; ++curr_time)
	{
		for (int i = 0; i < n; ++i)
		{
			for (int j = 0; j < n; ++j)
			{
				plant[i][j][curr_time]=plant[i][j][curr_time-1];
			}
		}
		for (int i = 0; i < n; ++i)
		{
			for (int j = 0; j < n; ++j)
			{
				if(plant[i][j][curr_time-1]==2)
				{
					for (int k = 0; k < 4; ++k)
					{
						if(is_valid(i+dr[k],j+dc[k]))
						{
							if(plant[i+dr[k]][j+dc[k]][curr_time-1]==0)
								plant[i+dr[k]][j+dc[k]][curr_time]=2;
						}
					}
				}
			}
		}
	}
	counter=1;
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			if(source_cap[i][j]!=0)
			{
				source_num[i][j]=counter;
				counter++;
			}
			else
				source_num[i][j]=-1;
		}
	}
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			if(sink_cap[i][j]!=0)
			{
				sink_num[i][j]=counter;
				counter++;
			}
			else
				sink_num[i][j]=-1;
		}
	}
	queue < pair <int,pair <int,int> > > bfs;
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			if(source_cap[i][j]==0)
				continue;
			bfs.push(pair <int,pair <int,int> > (0,pair <int,int> (i,j)));
			int source=source_num[i][j];
			vector < vector <bool> > vis(n,vector <bool> (n,false));
			vis[i][j]=true;
			while(!bfs.empty())
			{
				pair <int, pair <int,int> > top=bfs.front();
				bfs.pop();
				int curr_time=top.first,r=(top.second).first,c=(top.second).second;
				if(sink_cap[r][c]!=0)
					flo[source][sink_num[r][c]]=10000;
				if(curr_time==t)
					continue;
				if(plant[r][c][curr_time]!=0)
					continue;
				for (int k = 0; k < 4; ++k)
				{
					if(is_valid(r+dr[k],c+dc[k]) && plant[r+dr[k]][c+dc[k]][curr_time]==0 && !vis[r+dr[k]][c+dc[k]])
					{
						bfs.push(pair <int, pair <int,int> >(curr_time+1,pair <int,int> (r+dr[k],c+dc[k])));
						vis[r+dr[k]][c+dc[k]]=true;
					}
				}
			}
		}
	}
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			if(source_cap[i][j]!=0)
				flo[0][source_num[i][j]]=source_cap[i][j];
			if(sink_cap[i][j]!=0)
				flo[sink_num[i][j]][counter]=sink_cap[i][j];
		}
	}
	int temp,ans=0;
	while(true)
	{
		temp=get_path();
		if(temp==0)
			break;
		ans+=temp;
	}
	cout<<ans;
	return 0;
}


#include <cmath>
#include <ctime>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <functional>
#include <algorithm>
#include <iostream>
#include <numeric>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <list>
#include <set>
#include <map>
using namespace std;

#define debug(args...) fprintf(stderr,args)
#define foreach(_it,_v) for(typeof(_v.begin()) _it = _v.begin(); _it != _v.end(); ++_it)

typedef long long lint;
typedef pair<int,int> pii;
typedef pair<lint,lint> pll;

const int INF = 0x3f3f3f3f;
const lint LINF = 0x3f3f3f3f3f3f3f3fll;
const int MAXN = 20;
const int MAXV = 2*MAXN*MAXN;

char m1[MAXN][MAXN], m2[MAXN][MAXN];
int inf_time[MAXN][MAXN];
int n,t;

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

void bfs(int x,int y) {
    for(int a=0;a<n;++a)
        for(int b=0;b<n;++b)
            inf_time[a][b] = INF;
    inf_time[x][y] = 0;
    queue<pii> fila;
    fila.push(pii(x,y));
    while(!fila.empty()) {
        int cx = fila.front().first, cy = fila.front().second;
        fila.pop();
        for(int a=0;a<4;++a) {
            int nx = cx+dx[a], ny = cy+dy[a];
            if(nx >= n || ny >= n || nx < 0 || ny < 0) continue;
            if('0' <= m1[nx][ny] && m1[nx][ny] <= '9' && inf_time[nx][ny] == INF) {
                inf_time[nx][ny] = inf_time[cx][cy] + 1;
                fila.push(pii(nx,ny));
            }
        }
    }
}

bool foi[MAXN][MAXN];

vector<int> adj[MAXV];
int cap[MAXV][MAXV];

inline void insert_edge(int u,int v,int c) {
    adj[u].push_back(v);
    adj[v].push_back(u);
    cap[u][v] = c;
    cap[v][u] = 0;
}

int tempo[MAXN][MAXN];
bool dinic_foi[MAXV];
int dist[MAXV];

bool dinic_bfs(int s,int t) {
    memset(dist,-1,sizeof(dist));
    dist[s] = 0;
    queue<int> fila;
    fila.push(s);
    while(!fila.empty() && dist[t] == -1) {
        int v = fila.front();
        fila.pop();
        foreach(nxt,adj[v]) {
            if(!cap[v][*nxt] || dist[*nxt] != -1) continue;
            dist[*nxt] = dist[v] + 1;
            fila.push(*nxt);
        }
    }
    return dist[t] != -1;
}

void bfs2(int px,int py) {
    memset(tempo,INF,sizeof(tempo));
    tempo[px][py] = 0;
    if('1' <= m2[px][py] && m2[px][py] <= '9')
        insert_edge(n*px+py, n*n+n*px+py,INF);
    queue<pii> fila;
    fila.push(pii(px,py));
    while(!fila.empty()) {
        int x = fila.front().first, y = fila.front().second;
        fila.pop();
        for(int a=0;a<4;++a) {
            int nx = x+dx[a], ny = y+dy[a];
            if(nx >= n || ny >= n || nx < 0 || ny < 0) continue;
            if(tempo[nx][ny] != INF) continue;
            if(!('0' <= m1[nx][ny] && m1[nx][ny] <= '9')) continue;
            if(tempo[x][y] + 1 <= min(inf_time[nx][ny]-1,t)) {
                tempo[nx][ny] = tempo[x][y] + 1;
                fila.push(pii(nx,ny));
            }
            if(tempo[x][y] + 1 <= min(inf_time[nx][ny],t) && '1' <= m2[nx][ny] && m2[nx][ny] <= '9')
                insert_edge(n*px+py,n*n + n*nx + ny, INF);
        }
    }
}

int dinic_dfs(int v,int t,int flow) {
    if(v == t) return flow;
    dinic_foi[v] = 1;
    foreach(nxt,adj[v]) {
        if(!cap[v][*nxt] || dinic_foi[*nxt] || dist[*nxt] != dist[v] + 1) continue;
        int got = dinic_dfs(*nxt,t,min(flow,cap[v][*nxt]));
        if(got) {
            cap[v][*nxt] -= got;
            cap[*nxt][v] += got;
            return got;
        }
    }
    return 0;
}

int dinic(int s,int t) {
    int ret = 0, got;
    while(dinic_bfs(s,t)) {
        memset(dinic_foi,0,sizeof(dinic_foi));
        while(got = dinic_dfs(s,t,INF)) ret += got;
    }
    return ret;
}

int main() {
    scanf("%d%d",&n,&t);
    int ix,iy;
    int s = MAXV-2, t = MAXV-1;
    for(int a=0;a<n;++a) {
        for(int b=0;b<n;++b) {
            scanf(" %c",&m1[a][b]);
            if(m1[a][b] == 'Z') {
                ix = a; iy = b;
            }
            else if('1' <= m1[a][b] && m1[a][b] <= '9')
                insert_edge(s,a*n+b,m1[a][b]-'0');
        }
    }
    bfs(ix,iy);
    for(int a=0;a<n;++a) {
        for(int b=0;b<n;++b) {
            scanf(" %c",&m2[a][b]);
            if('1' <= m2[a][b] && m2[a][b] <= '9')
                insert_edge(n*n + a*n+b,t,m2[a][b]-'0');
        }
    }
    for(int a=0;a<n;++a)
        for(int b=0;b<n;++b)
            if('1' <= m1[a][b] && m1[a][b] <= '9')
                bfs2(a,b);
    printf("%d\n",dinic(s,t));
    return 0;
}


#include <cstdio>
#include <cctype>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

typedef pair <int, int> ii;

const int Inf = 1000000000;
const int Maxn = 11;
const int MaxN = 205;
const int Maxd = 4;
const int dy[Maxd] = {-1, 0, 1, 0};
const int dx[Maxd] = {0, -1, 0, 1};

int n, t;
char a[Maxn][Maxn], b[Maxn][Maxn];
int br, bc;
int bum[Maxn][Maxn];
int dist[Maxn][Maxn];
bool pos[Maxn][Maxn];
int N;
int R[MaxN][MaxN];
vector <int> neigh[MaxN];
int F[MaxN], P[MaxN];
int res;

void BFS1()
{
	fill((int*)bum, (int*)bum + Maxn * Maxn, t); bum[br][bc] = 0;
	queue <ii> Q; Q.push(ii(br, bc));
	while (!Q.empty()) {
		ii v = Q.front(); int d = bum[v.first][v.second]; Q.pop();
		for (int i = 0; i < Maxd; i++) {
			ii u = ii(v.first + dy[i], v.second + dx[i]);
			if (0 <= u.first && u.first < n && 0 <= u.second && u.second < n && a[u.first][u.second] != 'Y' && d + 1 < bum[u.first][u.second])
				bum[u.first][u.second] = d + 1, Q.push(u);
		}
	}
}

void BFS2(int sr, int sc)
{
	fill((int*)dist, (int*)dist + Maxn * Maxn, Inf); dist[sr][sc] = 0;
	fill((bool*)pos, (bool*)pos + Maxn * Maxn, false); pos[sr][sc] = true;
	queue <ii> Q; Q.push(ii(sr, sc));
	while (!Q.empty()) {
		ii v = Q.front(); int d = dist[v.first][v.second]; Q.pop();
		pos[v.first][v.second] = d <= bum[v.first][v.second];
		if (d >= bum[v.first][v.second]) continue;
		for (int i = 0; i < Maxd; i++) {
			ii u = ii(v.first + dy[i], v.second + dx[i]);
			if (0 <= u.first && u.first < n && 0 <= u.second && u.second < n && a[u.first][u.second] != 'Y' && d + 1 < dist[u.first][u.second])
				dist[u.first][u.second] = d + 1, Q.push(u);
		}
	}
}

void BFS(int sr, int sc, int dist[][Maxn], int Inf)
{
	fill((int*)dist, (int*)dist + Maxn * Maxn, Inf); dist[sr][sc] = 0;
	queue <ii> Q; Q.push(ii(sr, sc));
	while (!Q.empty()) {
		ii v = Q.front(); int d = dist[v.first][v.second]; Q.pop();
		for (int i = 0; i < Maxd; i++) {
			ii u = ii(v.first + dy[i], v.second + dx[i]);
			if (0 <= u.first && u.first < n && 0 <= u.second && u.second < n && a[u.first][u.second] != 'Y' && d + 1 < dist[u.first][u.second])
				dist[u.first][u.second] = d + 1, Q.push(u);
		}
	}
}

int getFlow()
{
	fill(F, F + N, 0); F[0] = Inf;
	priority_queue <ii> Q; Q.push(ii(Inf, 0));
	while (!Q.empty()) {
		int v = Q.top().second, f = Q.top().first; Q.pop();
		if (F[v] != f) continue;
		for (int i = 0; i < neigh[v].size(); i++) {
			int u = neigh[v][i];
			if (min(f, R[v][u]) > F[u]) F[u] = min(f, R[v][u]), P[u] = v, Q.push(ii(F[u], u));
		}
	}
	int v = N - 1;
	if (F[v] == 0) return 0;
	int res = F[v];
	while (v) {
		int u = P[v];
		R[u][v] -= res; R[v][u] += res;
		v = u;
	}
	return res;
}

int main()
{
	scanf("%d %d", &n, &t);
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			scanf(" %c", &a[i][j]);
			if (a[i][j] == 'Z') { br = i; bc = j; }
		}
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			scanf(" %c", &b[i][j]);
	BFS1();
	N = 2 * n * n + 2;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) if (isdigit(a[i][j]) && a[i][j] > '0') {
			int v = i * n + j + 1; R[0][v] = a[i][j] - '0'; neigh[0].push_back(v); neigh[v].push_back(0);
			BFS2(i, j);
			for (int i2 = 0; i2 < n; i2++)
				for (int j2 = 0; j2 < n; j2++) if (pos[i2][j2] && isdigit(b[i2][j2]) && b[i2][j2] > '0') {
					int u = n * n + i2 * n + j2 + 1; R[v][u] = Inf; neigh[v].push_back(u); neigh[u].push_back(v);
				}
		}
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) if (isdigit(b[i][j]) && b[i][j] > '0') {
			int u = n * n + i * n + j + 1; R[u][N - 1] = b[i][j] - '0'; neigh[u].push_back(N - 1); neigh[N - 1].push_back(u);
		}
	int f;
	while ((f = getFlow()) != 0) res += f;
	printf("%d\n", res);
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef pair<int,int> par;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    int T; cin >> R >> T;

    int zi = 0, zj = 0;

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

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

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

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

    init_maxflow( n , s , t );

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

    bfs2( zi , zj, 0 );

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

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

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


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

using namespace std;

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

struct kraw
{
    int a, res;
};

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

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

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


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

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

    // start and end point
    int s, t;

    // list array
    vector<edge> edg;

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

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

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

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

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

    	return visited[t];
    }

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

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

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

    	return flow;
    }

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

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

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

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

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

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

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

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

	BFS(x, y);

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

#define pb push_back
#define mp make_pair

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

typedef long long int64;
typedef unsigned long long uint64;

using namespace std;

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

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

int augment( int u ){

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

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

	return 0;

}

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

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

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

		if (!flow) return ans;

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

	return ans;
}

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

	ios::sync_with_stdio( false );

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

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

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

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

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

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

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

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

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

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

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

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

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

	cout << maxflow() << endl;

	return 0;
}


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


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

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

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

// Bitmask

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    if(tt>=t) return 0;

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

vector<string> lab, rea;

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


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

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

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

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

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

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

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

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

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

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

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

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