import java.util.*;
import java.io.*;
import java.util.Queue;
import java.util.LinkedList;
import java.math.*;

     public class Solution implements Runnable
    {

          public  static void solve()
          {

            int n = i();
            Double val = Math.sqrt(n);

            if (val.intValue() * val.intValue() == n){

               System.out.println(2*val.intValue());
             } else {
              if (((n-(val.intValue()*val.intValue()))/(1.0*val.intValue()))<=1){

               System.out.println(2*val.intValue() + 1);
              } else {
                 System.out.println(2*val.intValue() + 2);
              }
             }
           }

          public void run()
          {
              solve();
              out.close();
          }

          public static void main(String[] args) throws IOException
          {
                new Thread(null, new Solution(), "whatever", 1<<26).start();
          }
         abstract static class Pair implements Comparable<Pair>
         {
            long a;
            int b;

            Pair(){}
            Pair(long a,int b)
            {
                       this.a=a;
                       this.b=b;
            }

            public int compareTo(Pair x)
           {
                return Long.compare(x.a,this.a);
           }
        }

    ////////////////////////////////////////////////////// Merge Sort ////////////////////////////////////////////////////////////////////////

   static class Merge
   {

        public static void sort(long inputArr[])
        {
            int length = inputArr.length;
            doMergeSort(inputArr,0, length - 1);
        }

        private static void doMergeSort(long[] arr,int lowerIndex, int higherIndex)
        {
            if (lowerIndex < higherIndex) {
                int middle = lowerIndex + (higherIndex - lowerIndex) / 2;
                doMergeSort(arr,lowerIndex, middle);
                doMergeSort(arr,middle + 1, higherIndex);
                mergeParts(arr,lowerIndex, middle, higherIndex);
            }
        }

        private static void mergeParts(long[]array,int lowerIndex, int middle, int higherIndex)
        {
            long[] temp=new long[higherIndex-lowerIndex+1];
            for (int i = lowerIndex; i <= higherIndex; i++)
            {
                temp[i-lowerIndex] = array[i];
            }
            int i = lowerIndex;
            int j = middle + 1;
            int k = lowerIndex;
            while (i <= middle && j <= higherIndex)
            {
                if (temp[i-lowerIndex] < temp[j-lowerIndex])
                {
                    array[k] = temp[i-lowerIndex];
                    i++;
                } else {
                    array[k] = temp[j-lowerIndex];
                    j++;
                }
                k++;
            }
            while (i <= middle)
            {
                array[k] = temp[i-lowerIndex];
                k++;
                i++;
            }
            while(j<=higherIndex)
            {
                array[k]=temp[j-lowerIndex];
                k++;
                j++;
            }
        }

    }

    /////////////////////////////////////////////////////////// Methods ////////////////////////////////////////////////////////////////////////

     static boolean isPal(String s)
     {
        for(int i=0, j=s.length()-1;i<=j;i++,j--)
        {
                if(s.charAt(i)!=s.charAt(j)) return false;
        }
        return true;
     }
     static String rev(String s)
     {
                StringBuilder sb=new StringBuilder(s);
                sb.reverse();
                return sb.toString();
     }
     static int gcd(int a,int b){return (a==0)?b:gcd(b%a,a);}
     static long gcdExtended(long a,long b,long[] x)
     {

        if(a==0){
            x[0]=0;
            x[1]=1;
            return b;
        }
        long[] y=new long[2];
        long gcd=gcdExtended(b%a, a, y);

        x[0]=y[1]-(b/a)*y[0];
        x[1]=y[0];

        return gcd;
    }

     boolean findSum(int set[], int n, long sum)
    {
      if (sum == 0)
         return true;
      if (n == 0 && sum != 0)
         return false;
      if (set[n-1] > sum)
         return findSum(set, n-1, sum);
      return findSum(set, n-1, sum) ||findSum(set, n-1, sum-set[n-1]);
    }

      public static long modPow(long base, long exp, long mod)
     {
        base = base % mod;
        long result = 1;
        while (exp > 0)
       {
            if (exp % 2 == 1)
            {
                result = (result * base) % mod;
            }
            base = (base * base) % mod;
            exp = exp >> 1;
       }
        return result;
    }

    static long[] fac;
    static long[] inv;
    static long mod=(long)1e9+7;
    public static void cal()
    {
        fac = new long[1000005];
        inv = new long[1000005];
        fac[0] = 1;
        inv[0] = 1;
        for (int i = 1; i <= 1000000; i++)
        {
            fac[i] = (fac[i - 1] * i) % mod;
            inv[i] = (inv[i - 1] * modPow(i, mod - 2, mod)) % mod;
        }
    }

    public static long ncr(int n, int r)
    {
        return (((fac[n] * inv[r]) % mod) * inv[n - r]) % mod;
    }

////////////////////////////////////////// Input Reader ////////////////////////////////////////////////////////////////////////////////////////////////////

    static InputReader sc = new InputReader(System.in);
    static PrintWriter out= new PrintWriter(System.out);

    static class InputReader {

          private final InputStream stream;
          private final byte[] buf = new byte[8192];
          private int curChar, snumChars;
          private SpaceCharFilter filter;

          public InputReader(InputStream stream) {
                  this.stream = stream;
          }

          public int snext()
         {
                  if (snumChars == -1)
                          throw new InputMismatchException();
                  if (curChar >= snumChars) {
                          curChar = 0;
                          try {
                                  snumChars = stream.read(buf);
                          } catch (IOException e) {
                                  throw new InputMismatchException();
                          }
                          if (snumChars <= 0)
                                  return -1;
                  }
                  return buf[curChar++];
          }

          public int nextInt()
         {
                  int c = snext();
                  while (isSpaceChar(c))
                  {
                          c = snext();
                  }
                  int sgn = 1;
                  if (c == '-')
                  {
                          sgn = -1;
                          c = snext();
                  }
                  int res = 0;
                  do {
                          if (c < '0' || c > '9')
                                  throw new InputMismatchException();
                          res *= 10;
                          res += c - '0';
                          c = snext();
                  } while (!isSpaceChar(c));
                  return res * sgn;
          }

          public long nextLong()
          {
                  int c = snext();
                  while (isSpaceChar(c))
                  {
                          c = snext();
                  }
                  int sgn = 1;
                  if (c == '-')
                  {
                          sgn = -1;
                          c = snext();
                  }
                  long res = 0;
                  do {
                          if (c < '0' || c > '9')
                                  throw new InputMismatchException();
                          res *= 10;
                          res += c - '0';
                          c = snext();
                  } while (!isSpaceChar(c));
                  return res * sgn;
          }

          public int[] nextIntArray(int n)
          {
                  int a[] = new int[n];
                  for (int i = 0; i < n; i++)
                  {
                          a[i] = nextInt();
                  }
                  return a;
          }

          public long[] nextLongArray(int n)
          {
                  long a[] = new long[n];
                  for (int i = 0; i < n; i++)
                  {
                          a[i] = nextLong();
                  }
                  return a;
          }

          public String nextLine()
         {
                  int c = snext();
                  while (isSpaceChar(c))
                          c = snext();
                  StringBuilder res = new StringBuilder();
                  do {
                          res.appendCodePoint(c);
                          c = snext();
                  } while (!isEndOfLine(c));
                  return res.toString();
          }

          public boolean isSpaceChar(int c)
          {
                  if (filter != null)
                          return filter.isSpaceChar(c);
                  return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
          }

          private boolean isEndOfLine(int c)
          {
                  return c == '\n' || c == '\r' || c == -1;
          }

          public interface SpaceCharFilter
          {
                  public boolean isSpaceChar(int ch);
          }

    }

    static int i()
    {
        return sc.nextInt();
    }
    static long l(){
        return sc.nextLong();
    }
    static int[] iarr(int n)
    {
        return sc.nextIntArray(n);
    }
    static long[] larr(int n)
    {
        return sc.nextLongArray(n);
    }
    static String s(){
        return sc.nextLine();
    }

 }


import java.io.PrintWriter;
import java.util.Scanner;

public class Solution {
    public static void main(String[] args) { new Solution().run(); }

    private void run() {
        Scanner in = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);

        out.print(25);

        in.close();
        out.close();
    }
}


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class Solution implements Runnable {
  BufferedReader in;
  PrintWriter out;
  StringTokenizer tok = new StringTokenizer("");

  @Override
  public void run() {
    try {
      init();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
    long time = System.currentTimeMillis();
    try {
      solve();
    } catch (Exception e) {
      e.printStackTrace();
    }
    out.close();
    //System.err.println(System.currentTimeMillis() - time);
  }

  private void init() throws FileNotFoundException {
    String file = "";
    if (!file.equals("")) {
      in = new BufferedReader(new FileReader("input.txt"));
      out = new PrintWriter("output.txt");
    } else {
      in = new BufferedReader(new InputStreamReader(System.in));
      out = new PrintWriter(System.out);
    }
  }

  public static void main(String[] args) {
    new Thread(new Solution()).start();
  }

  private String readString() {
    while (!tok.hasMoreTokens()) {
      try {
        tok = new StringTokenizer(in.readLine());
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    return tok.nextToken();
  }

  private int readInt() {
    return Integer.parseInt(readString());
  }

  private long readLong() {
    return Long.parseLong(readString());
  }

  private void solve() {
    int n = readInt();
    int[] ar = new int[5];
    for (int i = 0; i < n; i++) {
      ar[readInt()-1]++;
    }
    for (int i = 0; i < n; i++) {
      ar[readInt()-1]--;
    }
    int count = 0;
    for (int i = 0; i < ar.length; i++) {
      if(Math.abs(ar[i]%2)==1) {
        out.print(-1);
        return;
      }
      count+= Math.abs(ar[i]/2);
    }
    out.print(count/2);

  }

}


import java.io.*;
import java.lang.*;
import java.util.*;

public class Main {
    public static MyScanner sc = new MyScanner(System.in);
    public static PrintWriter out = new PrintWriter(System.out);
    public static void main(String[] args) {
        int n = sc.nextint();
        int mod = sc.nextint();
        long[] dp1 = new long[n + 9];
        long[] dp2 = new long[n + 9];
        dp2[1] = 1;
        for(int i = 1; i <= n; i++){
            dp1[i] += dp1[i - 1];
            dp1[i] %= mod;
            dp2[i] = dp1[i];
            if(i == 1){
                dp2[i] = 1;
            }
            dp1[i + 1] += dp2[i];
            dp1[i + 1] %= mod;
            for(int j = 2; i * j <= n; j++){
                dp1[i * j] += dp2[i];
                dp1[i * j] %= mod;
                if((i + 1) * j <= n) {
                    dp1[(i + 1) * j] += mod - dp2[i];
                    dp1[(i + 1) * j] %= mod;
                }
            }
        }
        out.print(dp2[n]);
        out.close();
    }
}
class MyScanner {
    private BufferedReader br;
    private StringTokenizer tokenizer;

    public MyScanner(InputStream is) {
        br = new BufferedReader(new InputStreamReader(is));
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextint() {
        return Integer.parseInt(next());
    }
    public long nextlong() {
        return Long.parseLong(next());
    }
}


import static java.util.Arrays.*;
import static java.lang.Math.*;
import static java.math.BigInteger.*;
import java.util.*;
import java.math.*;
import java.io.*;

public class E implements Runnable
{
    String file = "input";

    boolean TEST = false;

    void solve() throws IOException
    {
        n = nextInt();
        T = nextInt();
        as = new char[n][];
        bs = new char[n][];
        for(int i = 0; i < n; i++) as[i] = next().toCharArray();
        for(int i = 0; i < n; i++) bs[i] = next().toCharArray();
        vs = new boolean[n][n][T + 1];
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                vs[i][j][0] = as[i][j] < '0' || as[i][j] > '9';
        for(int t = 1; t <= T; t++)
            for(int i = 0; i < n; i++)
                for(int j = 0; j < n; j++)
                {
                    if(vs[i][j][t - 1])
                    {
                        vs[i][j][t] = true;
                        continue;
                    }

                    for(int dx = -1; dx <= 1; dx++)
                        for(int dy = -1; dy <= 1; dy++)
                        {
                            if(abs(dx) + abs(dy) != 1) continue;

                            int px = i + dx;
                            int py = j + dy;
                            if(px < 0 || px >= n || py < 0 || py >= n) continue;

                            if(vs[px][py][t - 1] && as[px][py] != 'Y') vs[i][j][t] = true;
                        }
                }
        N = n * n;
        m = n * n * 2 + 2;
        cap = new int[m][m];
        st = m - 2;
        en = m - 1;
        //print(as[0][0]);
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                if(as[i][j] >= '0' && as[i][j] <= '9') BFS(i * n + j, as[i][j] - '0');

        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                if(as[i][j] >= '0' && as[i][j] <= '9') cap[st][i * n + j] = as[i][j] - '0';
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                if(bs[i][j] >= '0' && bs[i][j] <= '9') cap[i * n + j + N][en] = bs[i][j] - '0';

        //for(int i = 0; i < m - 2; i++)
        //  for(int j = 0; j < m - 2; j++)
        //      if(cap[i][j] > 0) print(i, j);

        out.println(runflow(st, en));
    }
    int[][] cap;
    int runflow(int st, int en)
    {
        int res = 0;
        while(true)
        {
            int flow = maxflow(st, en, INF, new boolean[m]);
            if(flow == 0) break;
            res += flow;
        }
        return res;
    }

    int maxflow(int st, int en, int curflow, boolean[] vs)
    {
        if(st == en) return curflow;

        for(int i = 0; i < m; i++)
            if(cap[st][i] > 0 && !vs[i])
            {
                vs[i] = true;
                int flow = maxflow(i, en, min(curflow, cap[st][i]), vs);
                if(flow > 0)
                {
                    cap[st][i] -= flow;
                    cap[i][st] += flow;
                    return flow;
                }
            }
        return 0;
    }
    int N;
    int INF = 1 << 20;
    void BFS(int st, int val)
    {
        Queue<Integer> q = new LinkedList<Integer>();
        int[] dist = new int[m];
        fill(dist, INF);
        q.offer(st);
        dist[st] = 0;
        if(bs[st / n][st % n] > '0' && bs[st / n][st % n] <= '9') cap[st][st + N] = val;
        while(!q.isEmpty())
        {
            int u = q.poll();
            if(dist[u] >= T) continue;

            int x = u / n, y = u % n;
            for(int dx = -1; dx <= 1; dx++)
                for(int dy = -1; dy <= 1; dy++)
                {
                    if(abs(dx) + abs(dy) != 1) continue;
                    int tx = x + dx;
                    int ty = y + dy;

                    if(tx < 0 || tx >= n || ty < 0 || ty >= n) continue;

                    if(vs[tx][ty][dist[u]]) continue;
                    int v = tx * n + ty;
                    if(!vs[tx][ty][dist[u] + 1])
                    {
                        if(dist[v] > dist[u] + 1)
                        {
                            dist[v] = dist[u] + 1;
                            q.offer(v);
                            cap[st][v + N] = val;
                        }
                    }
                    else if(bs[tx][ty] > '0' && bs[tx][ty] <= '9') cap[st][v + N] = val;
                }
        }
    }
    int m, st, en;
    char[][] as, bs;
    boolean[][][] vs;
    int n, T;

    String next() throws IOException
    {
        while(token == null || !token.hasMoreTokens()) token = new StringTokenizer(input.readLine());
        return token.nextToken();
    }

    int nextInt() throws IOException
    {
        return Integer.parseInt(next());
    }

    long nextLong() throws IOException
    {
        return Long.parseLong(next());
    }

    double nextDouble() throws IOException
    {
        return Double.parseDouble(next());
    }

    void print(Object... o)
    {
        System.out.println(deepToString(o));
    }

    void gcj(Object o)
    {
        String s = String.valueOf(o);
        out.println("Case #" + test + ": " + s);
        System.out.println("Case #" + test + ": " + s);
    }

    BufferedReader input;
    PrintWriter out;
    StringTokenizer token;
    int test;

    void init() throws IOException
    {
        if(TEST) input = new BufferedReader(new FileReader(file + ".in"));
        else input = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(new BufferedOutputStream(System.out));
    }

    public static void main(String[] args) throws IOException
    {
        new Thread(null, new E(), "", 1 << 20).start();
    }

    public void run()
    {
        try
        {
            init();
            if(TEST)
            {
                int runs = nextInt();
                for(int i = 0; i < runs; i++) solve();
            }
            else solve();
            out.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
            System.exit(1);
        }
    }
}


//package round70;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Scanner;

public class E {
	Scanner in;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni();
		int t = ni();
		char[][] map = new char[n][n]; // initial map
		char[][][] dmap = new char[t+1][n][n]; // dead map
		char[][] hmap = new char[n][n]; // hazard map
		int ct = 0, cct = 0;
		for(int i = 0;i < n;i++){
			map[i] = in.next().toCharArray();
			dmap[0][i] = Arrays.copyOf(map[i], n);
			for(int j = 0;j < n;j++){
				if(map[i][j] >= '1' && map[i][j] <= '9'){
					ct += map[i][j] - '0';
				}
			}
		}
		for(int i = 0;i < n;i++){
			hmap[i] = in.next().toCharArray();
			for(int j = 0;j < n;j++){
				if(hmap[i][j] >= '1' && hmap[i][j] <= '9'){
					cct += hmap[i][j] - '0';
				}
			}
		}

		int[] dr = {1,0,-1,0,0};
		int[] dc = {0,1,0,-1,0};
		for(int i = 1;i <= t;i++){
			for(int j = 0;j < n;j++){
				for(int k = 0;k < n;k++){
					if(dmap[i-1][j][k] == 'Z'){
						for(int l = 0;l < 5;l++){
							int nr = j + dr[l];
							int nc = k + dc[l];
							if(nr >= 0 && nr < n && nc >= 0 && nc < n && map[nr][nc] != 'Y'){
								dmap[i][nr][nc] = 'Z';
							}
						}
					}
				}
			}
//			tr(dmap[i]);
		}

		boolean[][] g = new boolean[n*n][n*n];
		BitSet[][][] alive = new BitSet[2][n*n][n*n];
		for(int i = 0;i < n;i++){
			for(int j = 0;j < n;j++){
				alive[0][i][j] = new BitSet();
				alive[1][i][j] = new BitSet();
				if(map[i][j] >= '1' && map[i][j] <= '9'){
					alive[0][i][j].set(i*n+j);
				}
			}
		}

		for(int i = 0;i < n;i++){
			for(int j = 0;j < n;j++){
				if(hmap[i][j] >= '1' && hmap[i][j] <= '9'){
					for(int l = alive[0][i][j].nextSetBit(0);l != -1;l = alive[0][i][j]
							.nextSetBit(l + 1)){
						g[l][i*n+j] = true;
					}
				}
			}
		}
		for(int k = 0, w = 0;k < t;k++, w^=1){
			for(int i = 0;i < n;i++){
				for(int j = 0;j < n;j++){
					alive[w^1][i][j].clear();
				}
			}
			for(int i = 0;i < n;i++){
				for(int j = 0;j < n;j++){
					if(k == 0 || dmap[k][i][j] != 'Z'){
						for(int l = 0;l < 5;l++){
							int nr = i + dr[l];
							int nc = j + dc[l];
							if(nr >= 0 && nr < n && nc >= 0 && nc < n && map[nr][nc] != 'Y' && dmap[k][nr][nc] != 'Z'){
								alive[w^1][nr][nc].or(alive[w][i][j]);
//								if(alive[w^1][nr][nc].get(8)){
//									tr(k, nr, nc);
//								}
							}
						}
					}
				}
			}
			for(int i = 0;i < n;i++){
				for(int j = 0;j < n;j++){
					if(hmap[i][j] >= '1' && hmap[i][j] <= '9'){
						for(int l = alive[w^1][i][j].nextSetBit(0);l != -1;l = alive[w^1][i][j]
								.nextSetBit(l + 1)){
							g[l][i*n+j] = true;
						}
					}
				}
			}
		}
//		for(int i = 0;i < n*n;i++){
//			tr(g[i]);
//		}

		int[] indc = new int[n*n+1];
		int[] inds = new int[n*n+1];
		for(int i = 0;i < n;i++){
			for(int j = 0;j < n;j++){
				indc[i*n+j+1] = indc[i*n+j] + (hmap[i][j] >= '1' && hmap[i][j] <= '9' ? hmap[i][j]-'0' : 0);
				inds[i*n+j+1] = inds[i*n+j] + (map[i][j] >= '1' && map[i][j] <= '9' ? map[i][j]-'0' : 0);
			}
		}

		boolean[][] lg = new boolean[ct][cct];
		for(int i = 0;i < n*n;i++){
			for(int j = 0;j < n*n;j++){
				if(g[i][j]){
					for(int k = inds[i];k < inds[i+1];k++){
						for(int l = indc[j];l < indc[j+1];l++){
							lg[k][l] = true;
						}
					}
				}
			}
		}
//		tr(lg);

		out.println(doBipartiteMatching(lg));
	}

	public static int doBipartiteMatching(boolean[][] g)
	{
		if(g.length == 0)return 0;
		if(g[0].length == 0)return 0;

		int n = g.length;
		int m = g[0].length;
		int[] im = new int[m];
		Arrays.fill(im, -1);
		for(int i = 0;i < n;i++){
			BitSet visited = new BitSet();
			visit(g, i, visited, im);
		}

		int ct = 0;
		for(int i = 0;i < m;i++){
			if(im[i] != -1)ct++;
		}
		return ct;
	}

	public static boolean visit(boolean[][] g, int cur, BitSet visited, int[] im)
	{
		if(cur == -1)return true;

		for(int i = visited.nextClearBit(0);i != g[cur].length;i = visited.nextClearBit(i+1)){
			if(g[cur][i]){
				visited.set(i);
				if(visit(g, im[i], visited, im)){
					im[i] = cur;
					return true;
				}
			}
		}
		return false;
	}

	void run() throws Exception
	{
		in = INPUT.isEmpty() ? new Scanner(System.in) : new Scanner(INPUT);
		out = new PrintWriter(System.out);

		solve();
		out.flush();
	}

	public static void main(String[] args) throws Exception
	{
		new E().run();
	}

	int ni() { return Integer.parseInt(in.next()); }
	double nd() { return Double.parseDouble(in.next()); }
	void tr(Object... o) { if(INPUT.length() != 0)System.out.println(Arrays.deepToString(o)); }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

/*
procrastinating
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int oo = (int) 2e9;
    static final long OO = (long) 4e18;
    static final int MOD = 998244353;

    static void dbg(Object... args) {
        for (Object a : args)
            out.print(a + " ");
        out.println();
    }

    static int n, t, nn;
    static char[][] a, b;
    static int[][] danger, c;
    static int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    static int[][][][][] dp;

    static class Pair {
        int x, y;

        Pair(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    static void bfs(int x0, int y0) {
        danger = new int[n][n];
        for (int i = 0; i < n; i++)
            Arrays.fill(danger[i], -1);
        danger[x0][y0] = 0;

        Pair[] q = new Pair[nn];
        int i = 0;
        q[i++] = new Pair(x0, y0);
        for (int j = 0; j < i; j++) {
            Pair fi = q[j];
            for (int[] dir : dirs) {
                int x = fi.x + dir[0];
                int y = fi.y + dir[1];
                if (x >= 0 && x < n && y >= 0 && y < n && a[x][y] < 'Y' && danger[x][y] == -1) {
                    danger[x][y] = danger[fi.x][fi.y] + 1;
                    q[i++] = new Pair(x, y);
                }
            }
        }
    }

    static void go(int t, int x0, int y0, int x1, int y1) {
        if (dp[t][x0][y0][x1][y1] != -1)
            return;

        if (t == 0) {
            if (x0 == x1 && y0 == y1)
                dp[t][x0][y0][x1][y1] = 2;
            else
                dp[t][x0][y0][x1][y1] = 0;
            return;
        }

        if (danger[x1][y1] != -1 && danger[x1][y1] < t) {
            dp[t][x0][y0][x1][y1] = 0;
            return;
        }

        int val = dp[t - 1][x0][y0][x1][y1];
        for (int[] dir : dirs) {
            int x = x1 + dir[0];
            int y = y1 + dir[1];
            if (x >= 0 && x < n && y >= 0 && y < n && a[x][y] < 'Y')
                val |= dp[t - 1][x0][y0][x][y];
        }

//        dbg(t, x0, y0, x1, y1, dp[t][x0][y0][x1][y1]);

        if ((val & 2) == 2)
            dp[t][x0][y0][x1][y1] = 2;
        else
            dp[t][x0][y0][x1][y1] = 0;

        if (dp[t][x0][y0][x1][y1] == 2 && danger[x1][y1] == t)
            dp[t][x0][y0][x1][y1] = 1;
    }

    static class FordFulkerson {
        int n;
        int[][] c;

        FordFulkerson(int[][] c) {
            this.c = c;
            n = c.length;
        }

        int findMaxFlow(int s, int t) {
            int[][] c1 = new int[n][n];
            for (int v = 0; v < n; v++)
                for (int u = 0; u < n; u++)
                    c1[v][u] = c[v][u];

            int maxFlow = 0;
            int[] par = new int[n];
            while (bfs(s, t, c1, par)) {
                int delta = oo;
                int v = t;
                while (v != s) {
                    int u = par[v];
                    delta = Math.min(delta, c1[u][v]);
                    v = u;
                }
                v = t;
                while (v != s) {
                    int u = par[v];
                    c1[u][v] -= delta;
                    c1[v][u] += delta;
                    v = u;
                }
                maxFlow += delta;
            }

            return maxFlow;
        }

        boolean bfs(int s, int t, int[][] c1, int[] par) {
            int[] q = new int[n];
            int i = 0;
            q[i++] = s;
            int[] d = new int[n]; Arrays.fill(d, -1);
            d[s] = 0;
            for (int j = 0; j < i; j++) {
                int v = q[j];
                for (int u = 0; u < n; u++) {
                    if (d[u] == -1 && c1[v][u] > 0) {
                        par[u] = v;
                        q[i++] = u;
                        d[u] = d[v] + 1;
                    }
                }
            }
            return d[t] != -1;
        }
    }

    static void print(int[][] arr) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++)
                out.print(arr[i][j] + " ");
            out.println();
        }
    }

    static void solve() {
        n = in.nextInt();
        t = in.nextInt();
        nn = n * n;

        a = new char[n][];
        for (int i = 0; i < n; i++)
            a[i] = in.next().toCharArray();

        b = new char[n][];
        for (int i = 0; i < n; i++)
            b[i] = in.next().toCharArray();

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

        bfs(xz, yz);
//        print(danger);

        dp = new int[t + 1][n][n][n][n];
        for (int i = 0; i <= t; i++)
            for (int x0 = 0; x0 < n; x0++)
                for (int y0 = 0; y0 < n; y0++)
                    for (int x1 = 0; x1 < n; x1++)
                        for (int y1 = 0; y1 < n; y1++)
                            if (a[x0][y0] < 'Y' && a[x1][y1] < 'Y') {
                                dp[i][x0][y0][x1][y1] = -1;
                                go(i, x0, y0, x1, y1);
                            }

        c = new int[nn * 2 + 2][nn * 2 + 2];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                if (a[i][j] < 'Y')
                    c[0][1 + i * n + j] = a[i][j] - '0';
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                if (b[i][j] < 'Y')
                    c[1 + nn + i * n + j][nn * 2 + 1] = b[i][j] - '0';
        for (int x0 = 0; x0 < n; x0++)
            for (int y0 = 0; y0 < n; y0++)
                for (int x1 = 0; x1 < n; x1++)
                    for (int y1 = 0; y1 < n; y1++)
                        for (int i = 0; i <= t; i++)
                            if (a[x0][y0] - '0' > 0 && b[x1][y1] - '0' > 0)
                                c[1 + x0 * n + y0][1 + nn + x1 * n + y1] |= (dp[i][x0][y0][x1][y1] != 0 ? 10 : 0);

//        print(c);

        FordFulkerson ff = new FordFulkerson(c);
        int ans = ff.findMaxFlow(0, nn * 2 + 1);

        out.println(ans);

    }

    public static void main(String[] args) throws FileNotFoundException {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("sometext.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        solve();

//        Thread thread = new Thread(null, () -> {
//            solve();
//        }, "Main", 1 << 28);
//        thread.start();
//        try {
//            thread.join();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

//        out.flush();
        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.OutputStream;
import java.util.Arrays;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.BufferedOutputStream;
import java.util.List;
import java.util.StringTokenizer;
import java.io.Writer;
import java.io.BufferedReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author An Almost Retired Guy
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        TaskE solver = new TaskE();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskE {
        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int n = in.nextInt(), t = in.nextInt();
            char[][] scientists = in.nextCharArray2(n, n), capsules = in.nextCharArray2(n, n);
            boolean[][] table = new boolean[n][n];
            int x0 = -1, y0 = -1;
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++) {
                    table[i][j] = Character.isDigit(scientists[i][j]);
                    if (scientists[i][j] == 'Z') {
                        x0 = i;
                        y0 = j;
                    }
                }
            int n2 = n * n, N = 2 * n2 + 2, sink = N - 1, source = sink - 1;
            ArrayList<MaxFlowDinic.Edge>[] graph = new ArrayList[N];
            for (int i = 0; i < N; i++) graph[i] = new ArrayList<>();
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                    MaxFlowDinic.addEdge(graph, source, i * n + j, table[i][j] ? scientists[i][j] - '0' : 0);
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                    MaxFlowDinic.addEdge(graph, n2 + i * n + j, sink, table[i][j] ? capsules[i][j] - '0' : 0);
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                    for (int k = 0; k < n; k++)
                        for (int l = 0; l < n; l++)
                            if (f(table, i, j, k, l, x0, y0, t)) {
                                if (table[i][j] && table[k][l] && scientists[i][j] != '0' && capsules[k][l] != '0')
                                    System.err.println(i + " " + j + " " + k + " " + l);
                                MaxFlowDinic.addEdge(graph, i * n + j, n2 + k * n + l, Integer.MAX_VALUE);
                            }
            int ans = MaxFlowDinic.maxFlow(graph, source, sink);
            out.println(ans);
        }

        boolean f(boolean[][] table, int xs, int ys, int xe, int ye, int x0, int y0, int t) {
            int n = table.length;
            int[][] last = new int[n][n], now = new int[n][n];
            final int[] dx = new int[]{-1, 0, 0, 1}, dy = new int[]{0, -1, 1, 0};
            now[xs][ys] = 1;
            now[x0][y0] = -1;
            while (t-- > 0) {
                boolean can1 = false;
                for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) last[i][j] = now[i][j];
                for (int i = 0; i < n; i++)
                    for (int j = 0; j < n; j++)
                        if (last[i][j] == 1) for (int k = 0; k < 4; k++) {
                            int i2 = i + dx[k], j2 = j + dy[k];
                            if (i2 >= 0 && i2 < n && j2 >= 0 && j2 < n && table[i2][j2] && now[i2][j2] == 0) {
                                now[i2][j2] = 1;
                                can1 = true;
                            }
                        }
                boolean can2 = false;
                for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) last[i][j] = now[i][j];
                for (int i = 0; i < n; i++)
                    for (int j = 0; j < n; j++)
                        if (last[i][j] == -1) for (int k = 0; k < 4; k++) {
                            int i2 = i + dx[k], j2 = j + dy[k];
                            if (i2 >= 0 && i2 < n && j2 >= 0 && j2 < n && table[i2][j2] && (now[i2][j2] == 0 || (now[i2][j2] == 1 && (i2 != xe || j2 != ye)))) {
                                now[i2][j2] = -1;
                                can2 = true;
                            }
                        }
                if (!can1 && !can2) break;
            }
            return now[xe][ye] == 1;
        }

    }

    static class MaxFlowDinic {
        public static void addEdge(List<MaxFlowDinic.Edge>[] graph, int s, int t, int cap) {
            graph[s].add(new MaxFlowDinic.Edge(t, graph[t].size(), cap));
            graph[t].add(new MaxFlowDinic.Edge(s, graph[s].size() - 1, 0));
        }

        static boolean dinicBfs(List<MaxFlowDinic.Edge>[] graph, int src, int dest, int[] dist) {
            Arrays.fill(dist, -1);
            dist[src] = 0;
            int[] Q = new int[graph.length];
            int sizeQ = 0;
            Q[sizeQ++] = src;
            for (int i = 0; i < sizeQ; i++) {
                int u = Q[i];
                for (MaxFlowDinic.Edge e : graph[u]) {
                    if (dist[e.t] < 0 && e.f < e.cap) {
                        dist[e.t] = dist[u] + 1;
                        Q[sizeQ++] = e.t;
                    }
                }
            }
            return dist[dest] >= 0;
        }

        static int dinicDfs(List<MaxFlowDinic.Edge>[] graph, int[] ptr, int[] dist, int dest, int u, int f) {
            if (u == dest)
                return f;
            for (; ptr[u] < graph[u].size(); ++ptr[u]) {
                MaxFlowDinic.Edge e = graph[u].get(ptr[u]);
                if (dist[e.t] == dist[u] + 1 && e.f < e.cap) {
                    int df = dinicDfs(graph, ptr, dist, dest, e.t, Math.min(f, e.cap - e.f));
                    if (df > 0) {
                        e.f += df;
                        graph[e.t].get(e.rev).f -= df;
                        return df;
                    }
                }
            }
            return 0;
        }

        public static int maxFlow(List<MaxFlowDinic.Edge>[] graph, int src, int dest) {
            int flow = 0;
            int[] dist = new int[graph.length];
            while (dinicBfs(graph, src, dest, dist)) {
                int[] ptr = new int[graph.length];
                while (true) {
                    int df = dinicDfs(graph, ptr, dist, dest, src, Integer.MAX_VALUE);
                    if (df == 0)
                        break;
                    flow += df;
                }
            }
            return flow;
        }

        public static class Edge {
            public int t;
            public int rev;
            public int cap;
            public int f;

            public Edge(int t, int rev, int cap) {
                this.t = t;
                this.rev = rev;
                this.cap = cap;
            }

        }

    }

    static class InputReader {
        BufferedReader br;
        StringTokenizer st;

        public InputReader(InputStream inputStream) {
            br = new BufferedReader(new InputStreamReader(inputStream));
        }

        public String next() {
            while (st == null || !st.hasMoreElements()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public String nextString() {
            return next();
        }

        public char[] nextCharArray(int n) {
            char[] a = nextString().toCharArray();
            assert (a.length == n);
            return a;
        }

        public char[][] nextCharArray2(int n, int m) {
            char[][] a = new char[n][];
            for (int i = 0; i < n; i++) a[i] = nextCharArray(m);
            return a;
        }

        public String nextLine() {
            try {
                return br.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

    static class OutputWriter extends PrintWriter {
        public OutputWriter(OutputStream outputStream) {
            super(new BufferedOutputStream(outputStream));
        }

        public OutputWriter(Writer writer) {
            super(writer);
        }

        public void close() {
            super.close();
        }

    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Evacuation {
	static class MaxFlow_EdmondsKarp {

		/**
		 * @param args
		 */

		public static int maxflow(int[][] cap,int src,int dest){
			int cost=0;
			int c=0;
			int[][] flow=new int[cap.length][cap[0].length];
			while((c=bfs(cap,src,dest,flow))!=0){
				cost+=c;
			}

			return cost;
		}
		private static int bfs(int[][] cap, int src, int dest,int[][] flow) {
			Queue<Integer> q=new LinkedList<Integer>();
			q.add(src);
			boolean[] vis=new boolean[cap.length];
			vis[src]=true;
			int[] parent=new int[cap.length];
			Arrays.fill(parent, -1);
			while(!q.isEmpty()){
				int front=q.remove();
				if(front==dest)break;
				for(int i=0;i<cap[front].length;i++){
					if(vis[i]||cap[front][i]<=0)continue;
					vis[i]=true;
					parent[i]=front;
					q.add(i);
				}
			}
			int current=dest;
			int min=Integer.MAX_VALUE;
			while(parent[current]!=-1){
				min=Math.min(min,cap[parent[current]][current]);
				current=parent[current];
			}
			current=dest;
			while(parent[current]!=-1){
				cap[parent[current]][current]-=min;
				cap[current][parent[current]]+=min;
				flow[current][parent[current]]-=min;
				flow[parent[current]][current]+=min;
				current=parent[current];
			}
			return min==Integer.MAX_VALUE?0:min;
		}

	}

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader r=new BufferedReader(new InputStreamReader(System.in));
			String s1=r.readLine();
			String[] sp=s1.split("[ ]+");
			int n=new Integer(sp[0]);
			int m=new Integer(sp[0]);
			int t=new Integer(sp[1]);
			char[][] arr=new char[n][m];
			int x=-1,y=-1;
			for (int i = 0; i < arr.length; i++) {
				arr[i]=r.readLine().toCharArray();
				for (int j = 0; j < arr[i].length; j++) {
					if(arr[i][j]=='Z'){
						x=i;
						y=j;
					}
				}
			}
			r.readLine();
			char[][] rescue = new char[n][m];
			for (int i = 0; i < rescue.length; i++) {
				rescue[i]=r.readLine().toCharArray();
			}
			int[][] inf=new int[n][m];
			for (int i = 0; i < inf.length; i++) {
				Arrays.fill(inf[i], t);
			}
			Queue<Integer> q=new LinkedList<Integer>();
			q.add(x);
			q.add(y);
			q.add(0);
			boolean[][] vis=new boolean[n][m];
			vis[x][y]=true;
			int[] dx={1,-1,0,0};
			int[] dy={0,0,1,-1};
			while(!q.isEmpty()){
				int fx = q.remove();
				int fy = q.remove();
				int fc = q.remove();
				if(fc>t)break;
				inf[fx][fy]=fc;
				for(int i=0;i<4;i++){
					int nx=fx+dx[i];
					int ny=fy+dy[i];
					if(nx>=0&&nx<n&&ny>=0&&ny<m&&!vis[nx][ny]&&arr[nx][ny]!='Y'&&arr[nx][ny]!='Z'){
						q.add(nx);
						q.add(ny);
						q.add(fc+1);
						vis[nx][ny]=true;
					}
				}
			}
		int[][] cap=new int[n*n*2+2][n*n*2+2]; // 2*n^2 + 2
		// first i*n+j , second n*n+a*n+b , src n*n*2 dest n*n*2+1
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				for(int a=0;a<n;a++){
					for(int b=0;b<n;b++){
						if(arr[i][j]>'0'&&arr[i][j]<='9'&&rescue[a][b]>'0'&&rescue[a][b]<='9'){
							boolean can = false;
							q=new LinkedList<Integer>();
							q.add(i);
							q.add(j);
							q.add(0);
							vis=new boolean[n][m];
							vis[i][j]=true;
							while(!q.isEmpty()){
								int fx = q.remove();
								int fy = q.remove();
								if(fx==a&&fy==b){
									can=true;
									break;
								}
								int ft = q.remove();
								if(inf[fx][fy]<=ft)continue;
								for(int u=0;u<4;u++){
									int nx=fx+dx[u];
									int ny=fy+dy[u];
									if(nx>=0&&nx<n&&ny>=0&&ny<m&&!vis[nx][ny]&&arr[nx][ny]!='Y'&&(inf[nx][ny]>=ft+1)){
										q.add(nx);
										q.add(ny);
										q.add(ft+1);
										vis[nx][ny]=true;
									}
								}
							}
							if(can){
								cap[i*n+j][n*n+a*n+b]=Math.min(arr[i][j]-'0',rescue[a][b]-'0');
							}
						}
					}
				}
			}
		}
		for(int i=0;i<n*n;i++){
			if(arr[i/n][i%n]>='1'&&arr[i/n][i%n]<='9')
				cap[n*n*2][i]=arr[i/n][i%n]-'0';
			else
				cap[n*n*2][i]=0;
		}
		for(int i=0;i<n*n;i++){
			if(rescue[i/n][i%n]>='1'&&rescue[i/n][i%n]<='9')
				cap[n*n+i][2*n*n+1]=rescue[i/n][i%n]-'0';
			else
				cap[n*n+i][2*n*n+1]=0;
		}

		int max = MaxFlow_EdmondsKarp.maxflow(cap, n*n*2, 2*n*n+1);
		System.out.println(max);

	}
}


import java.util.LinkedList;
import java.util.InputMismatchException;
import java.io.*;
import java.util.Arrays;
import java.util.Queue;

/**
 * Generated by Contest helper plug-in
 * Actual solution is at the bottom
 */
public class Main {
    public static void main(String[] args) {
        InputReader in = new StreamInputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);
        run(in, out);
    }

    public static void run(InputReader in, PrintWriter out) {
        Solver solver = new Matching();
        solver.solve(1, in, out);
        Exit.exit(in, out);
    }
}

class StreamInputReader extends InputReader {
    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar, numChars;

    public StreamInputReader(InputStream stream) {
        this.stream = stream;
        curChar = 0;
    }

    public int read() {
        if (numChars == -1)
            throw new InputMismatchException();
        if (curChar >= numChars) {
            curChar = 0;
            try {
                numChars = stream.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar++];
    }

    @Override
    public void close() {
        try {
            stream.close();
        } catch (IOException ignored) {
        }
    }
}

abstract class InputReader {
    private boolean finished = false;

    public abstract int read();

    public int nextInt() {
        return Integer.parseInt(nextToken());
    }
    public String readString() {
        return readLine();
    }

    public String readLine() {
        StringBuffer res = new StringBuffer();
        do {
            int c = read();
            if (isEndOfLineChar(c)) {
                return res.toString();
            }
            res.appendCodePoint(c);
        }  while (true) ;
    }
    public String nextToken() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        StringBuffer res = new StringBuffer();
        do {
            res.appendCodePoint(c);
            c = read();
        } while (!isSpaceChar(c));
        return res.toString();
    }
    private boolean isEndOfLineChar(int c) {
        return c == '\n' || c == '\r' || c == -1;
    }
    private boolean isSpaceChar(int c) {
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public void setFinished(boolean finished) {
        this.finished = finished;
    }

    public abstract void close();
}

interface Solver {
    public void solve(int testNumber, InputReader in, PrintWriter out);
}

class Exit {
    private Exit() {
    }

    public static void exit(InputReader in, PrintWriter out) {
        in.setFinished(true);
        in.close();
        out.close();
    }
}

class Matching implements Solver {
    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int size = in.nextInt();
        int bomb = in.nextInt();
        char doctors[][] = new char[size][size];
        char capsuls[][] = new char[size][size];
        for (int i = 0; i < size; ++i) {
            doctors[i] = in.nextToken().toCharArray();
        }
        for (int i = 0; i < size; ++i) {
            capsuls[i] = in.nextToken().toCharArray();
        }

        Queue<Point> Q = new LinkedList<Point>() ;
        int dist[][] = new int[size][size];
        for (int[] a : dist) Arrays.fill(a, Integer.MAX_VALUE / 10);
        for (int i = 0; i < size; ++i)
            for (int j = 0; j < size; ++j)
                if (doctors[i][j] == 'Z') {
                    dist[i][j] = 0;
                    Q.add(new Point(j, i));
                }
        int dj[] = {-1, 1, 0, 0};
        int di[] = {0, 0, -1, 1};
        while (Q.size() > 0) {
            Point p = Q.poll();
            int j = p.x;
            int i = p.y;
            for (int u = 0; u < di.length; ++u) {
                int ni = i + di[u];
                int nj = j + dj[u];
                if (ni >= 0 && nj >= 0 && ni < size && nj < size && dist[ni][nj] == Integer.MAX_VALUE / 10 && Character.isDigit(capsuls[ni][nj])) {
                    dist[ni][nj] = dist[i][j]  + 1;
                    Q.add(new Point(nj, ni));
                }
            }
        }
       /* out.print("curse dist : \n");
        for (int d[] : dist) {
            out.print(Arrays.toString(d) + "\n"); out.flush();;
        */
        int d[][][][][] = new int[size][size][bomb + 2][size][size];
        for (int a[][][][] : d)
            for (int b[][][] : a)
                for (int c[][] : b)
                    for (int e[] : c)
                        Arrays.fill(e, -1);
        for (int y = 0; y < size; ++y) {
            for (int x = 0; x < size; ++x) {
                if (Character.isDigit(doctors[y][x]) && doctors[y][x] - '0' >= 0) {
                  Queue<Tuples> queue = new LinkedList<Tuples>();
                    queue.add(new Tuples(x, y, 0));
                    d[y][x][0][y][x] = 1;
                    while (queue.size() > 0) {
                        Tuples p = queue.poll();
                        int i = p.y;
                        int j = p.x;
                        int time = p.time;
                        for (int u = 0; u < di.length; ++u) {
                            int ni = i + di[u];
                            int nj = j + dj[u];

                            if (ni >= 0 && nj >= 0 && ni < size && nj < size && time + 1 <= bomb && d[y][x][time + 1][ni][nj] == -1 && dist[ni][nj] >= time + 1 && Character.isDigit(doctors[ni][nj]) ) {
                                if (dist[ni][nj] > time + 1)
                                    queue.add(new Tuples(nj, ni, time + 1));
                                d[y][x][time + 1][ni][nj] = 1;
                            }
                        }
                    }
                }
            }
        }

        int nodes = size * size * 2 + 2;
        int src = nodes - 2;
        int des= nodes - 1;
        int capa[][] = new int[nodes][nodes];
        int flow[][] = new int[nodes][nodes];
        int prev[] = new int[nodes];
        for (int y = 0; y < size; ++y) {
            for (int x= 0; x <size; ++x) {
                if (Character.isDigit(doctors[y][x]) && doctors[y][x] - '0' > 0) {
                    capa[src][y * size + x] = doctors[y][x] - '0';
                    for (int i = 0; i < size; ++i)
                        for (int j = 0; j < size; ++j) {
                            for (int t = 0; t <= bomb; ++t)
                                if (d[y][x][t][i][j] >= 0 && Character.isDigit(capsuls[i][j]) && capsuls[i][j] - '0' > 0) {
                                    capa[y * size + x][size * size + i * size + j] = Integer.MAX_VALUE / 10;
                               //     out.println("add edge" + "(" + y + ", " + x + ")" + "->" + "(" + i + ", " + j + ")" );
                                }
                        }
                }
            }
        }
        for (int y = 0; y < size; ++y) {
            for (int x = 0; x < size; ++x)
                if (Character.isDigit(capsuls[y][x]) && capsuls[y][x] - '0' > 0) {
                    capa[size * size + y * size + x][des] = capsuls[y][x] - '0';
                }
        }

        int res = 0;
        while (true) {
            int q[] = new int[nodes];
            int dd[] = new int[nodes];
            int h = 0;
            q[h ++] = src;
            dd[src] = 1;
            for (int i = 0; i < h; ++i) {
                int cur = q[i];
                for (int j = 0; j < nodes; ++j) {
                    if (capa[cur][j] - flow[cur][j] > 0 && dd[j] == 0) {
                        prev[j] = cur;
                        q[h ++] = j;
                        dd[j] = 1;
                    }
                }
            }
            if (dd[des] == 0) break;
            int add = Integer.MAX_VALUE / 10;
            for (int cur = des; cur != src; cur = prev[cur]) {
                int p = prev[cur];
                add = Math.min(add, capa[p][cur] - flow[p][cur]);
            }
            for (int cur = des; cur != src; cur = prev[cur]) {
                int p = prev[cur];
                flow[p][cur] += add;
                flow[cur][p] -= add;
            }
            res += add;
        }
        out.print(res);
    }
    class Tuples {
        int x, y, time;

        Tuples(int x, int y, int time) {
            this.x = x;
            this.y = y;
            this.time = time;
        }
    }
    class Point {
        int x, y;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
}


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Queue;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

public class Solution implements Runnable {

	public static void main(String[] args) {
		(new Thread(new Solution())).start();
	}

	BufferedReader in;
	PrintWriter out;
	StringTokenizer st;

	String nextToken() throws IOException {
		while (st == null || !st.hasMoreTokens()) {
			String r = in.readLine();
			if (r == null) return null;
			st = new StringTokenizer(r);
		}
		return st.nextToken();
	}

	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}

	int[][] a = new int[10][10];
	int[][] b = new int[10][10];
	int[][] c = new int[10][10];
	boolean[][] mat;
	boolean[] w;
	int t, n;

	void bfsc(int x, int y) {
		c[x][y] = 1;
		for (int tt = 1; tt <= t; tt++) {
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < n; j++) {
					if (a[i][j] >= 0 && c[i][j] == 0) {
						if (i > 0 && c[i - 1][j] == tt) c[i][j] = tt + 1;
						if (j > 0 && c[i][j - 1] == tt) c[i][j] = tt + 1;
						if (j < n - 1 && c[i][j + 1] == tt) c[i][j] = tt + 1;
						if (i < n - 1 && c[i + 1][j] == tt) c[i][j] = tt + 1;
					}
				}
			}
		}
	}

	void bfs(int x, int y) {
		int[][] d = new int[10][10];
		d[x][y] = 1;
		Queue<Integer> qx = new LinkedList<Integer>();
		Queue<Integer> qy = new LinkedList<Integer>();
		Queue<Integer> qt = new LinkedList<Integer>();
		qx.add(x); qy.add(y); qt.add(0);
		while (!qx.isEmpty()) {
			int xx = qx.poll(), yy = qy.poll(), tt = qt.poll();
			if (tt == t) break;
			if (c[xx][yy] == tt + 1) continue;
			if (xx > 0 && a[xx - 1][yy] >= 0 && d[xx - 1][yy] == 0 && (c[xx - 1][yy] == 0 || c[xx - 1][yy] > tt + 1)) {
				d[xx - 1][yy] = 1;
				qx.add(xx - 1); qy.add(yy); qt.add(tt + 1);
			}
			if (yy > 0 && a[xx][yy - 1] >= 0 && d[xx][yy - 1] == 0 && (c[xx][yy - 1] == 0 || c[xx][yy - 1] > tt + 1)) {
				d[xx][yy - 1] = 1;
				qx.add(xx); qy.add(yy - 1); qt.add(tt + 1);
			}
			if (xx < n - 1 && a[xx + 1][yy] >= 0 && d[xx + 1][yy] == 0 && (c[xx + 1][yy] == 0 || c[xx + 1][yy] > tt + 1)) {
				d[xx + 1][yy] = 1;
				qx.add(xx + 1); qy.add(yy); qt.add(tt + 1);
			}
			if (yy < n - 1 && a[xx][yy + 1] >= 0 && d[xx][yy + 1] == 0 && (c[xx][yy + 1] == 0 || c[xx][yy + 1] > tt + 1)) {
				d[xx][yy + 1] = 1;
				qx.add(xx); qy.add(yy + 1); qt.add(tt + 1);
			}
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (d[i][j] == 1 && b[i][j] > 0) {
					for (int k1 = 0; k1 < a[x][y]; k1++) {
						for (int k2 = 0; k2 < b[i][j]; k2++) {
							mat[x * 100 + y * 10 + k1][i * 100 + j * 10 + k2] =
								mat[x * 100 + y * 10 + k1][i * 100 + j * 10 + k2] = true;
						}
					}
				}
			}
		}
	}

	int[] px = new int[1010];

	boolean dfs(int q) {
		w[q] = true;
		for (int i = 0; i < 1000; i++) {
			if (mat[q][i]) {
				if (px[i] == -1 || !w[px[i]] && dfs(px[i])) {
					px[i] = q;
					return true;
				}
			}
		}
		return false;
	}

	void solve() throws Exception {
		n = nextInt();
		t = nextInt();
		mat = new boolean[1010][1010];
		w = new boolean[1010];
		for (int i = 0; i < n; i++) {
			String s = nextToken();
			for (int j = 0; j < n; j++) {
				if (s.charAt(j) == 'Y') a[i][j] = -1; else
					if (s.charAt(j) == 'Z') a[i][j] = -2; else
						a[i][j] = s.charAt(j) - '0';
			}
		}
		for (int i = 0; i < n; i++) {
			String s = nextToken();
			for (int j = 0; j < n; j++) {
				if (s.charAt(j) == 'Y') b[i][j] = 10; else
					if (s.charAt(j) == 'Z') b[i][j] = 11; else
						b[i][j] = s.charAt(j) - '0';
			}
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (a[i][j] == -2) bfsc(i, j);
			}
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (a[i][j] > 0) bfs(i, j);
			}
		}
		int ans = 0;
		Arrays.fill(px, -1);
		for (int i = 0; i < 1000; i++) {
			Arrays.fill(w, false);
			if (dfs(i)) ans++;
		}
		out.println(ans);
	}

	public void run() {
		Locale.setDefault(Locale.UK);
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
//			in = new BufferedReader(new FileReader("input.txt"));
//			out = new PrintWriter("output.txt");
			solve();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		} finally {
			out.flush();
		}
	}

}


//package codeforces.br70;

import javax.management.Query;
import java.io.*;
import java.math.*;
import java.util.*;

public class ProblemE {

    int[][] dir = new int[][] {{1,0},{0,1},{-1,0},{0,-1}};

    private class Point {
        public int x,y;
        public Point(int xx, int yy) {
            x = xx;
            y = yy;
        }

        public Point(Point p, int ind) {
            x = p.x + dir[ind][0];
            y = p.y + dir[ind][1];
        }

        public boolean valid() {
            return x >= 0 && x < n && y >= 0 && y < n;
        }
    }

    private int[] pair1;
    private int[] pair2;
    private boolean[] used;
    List<ArrayList<Integer>> g;
    private int n;

     public void solve() {
        boolean oj = true;

        try {
            Reader reader = oj ? new InputStreamReader(System.in) : new FileReader("E.in");
            Writer writer = oj ? new OutputStreamWriter(System.out) : new FileWriter("E.out");
            BufferedReader br = new BufferedReader(reader);
            StreamTokenizer st = new StreamTokenizer(reader);
            PrintWriter out = new PrintWriter(writer);

            MyTokenizer tok = new MyTokenizer(br.readLine());

            n = tok.getInteger();
            int t = tok.getInteger();

            Point z = null;

            char[][] sci = new char[n][n];
            char[][] caps = new char[n][n];

            List<Point> scis = new ArrayList<Point>();
            List<ArrayList<Integer>> v1 = new ArrayList<ArrayList<Integer>>();

            int cc = 0;
            for(int i=0;i<n;i++) {
                String s = br.readLine();
                for(int j=0;j<n;j++) {
                    sci[i][j] = s.charAt(j);
                    if (sci[i][j] == 'Z') {
                        z = new Point(i, j);
                    }
                    if (sci[i][j] > '0' && sci[i][j] <= '9') {
                        Point pp = new Point(i, j);
                        scis.add(pp);

                        ArrayList<Integer> list = new ArrayList<Integer>();
                        v1.add(list);
                        int num = sci[i][j] - '0';
                        for(int k=0;k<num;k++) {
                            list.add(cc);
                            cc++;
                        }
                    }
                }
            }

            int numsci = cc;

            br.readLine();

            List<Point> allcaps = new ArrayList<Point>();
            List<ArrayList<Integer>> v2 = new ArrayList<ArrayList<Integer>>();
            int[][] p = new int[n][n];

            cc = 0;

            for(int i=0;i<n;i++) {
                String s = br.readLine();
                for(int j=0;j<n;j++) {
                    caps[i][j] = s.charAt(j);
                    p[i][j] = -1;
                    if (caps[i][j] > '0' && caps[i][j] <= '9') {
                        Point pp = new Point(i, j);
                        allcaps.add(pp);
                        p[i][j] = allcaps.size() - 1;

                        ArrayList<Integer> list = new ArrayList<Integer>();
                        v2.add(list);
                        int num = caps[i][j] - '0';
                        for(int k=0;k<num;k++) {
                            list.add(cc);
                            cc++;
                        }
                    }
                }
            }

            int numcaps = cc;

            int[][] zdist = new int[n][n];
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    zdist[i][j] = -1;

            Queue<Point> q = new LinkedList<Point>();
            q.add(z);

            zdist[z.x][z.y] = 0;

            while (!q.isEmpty()) {
                Point cur = q.remove();
                for(int i=0;i<4;i++) {
                    Point next = new Point(cur, i);
                    if (next.valid() && zdist[next.x][next.y] == -1 && sci[next.x][next.y] != 'Y') {
                        zdist[next.x][next.y] = zdist[cur.x][cur.y] + 1;
                        q.add(next);
                    }
                }
            }

            g = new ArrayList<ArrayList<Integer>>();
            for(int i=0;i<numsci;i++)
                g.add(new ArrayList<Integer>());

            for (int i1 = 0, scisSize = scis.size(); i1 < scisSize; i1++) {
                Point sc = scis.get(i1);

                int numsc = sci[sc.x][sc.y] - '0';

                int[][] scdist = new int[n][n];
                for (int i = 0; i < n; i++)
                    for (int j = 0; j < n; j++)
                        scdist[i][j] = -1;

                q.clear();
                scdist[sc.x][sc.y] = 0;
                q.add(sc);

                if (p[sc.x][sc.y] >= 0) {
                    int capnum = p[sc.x][sc.y];
                    for(int i=0;i<v1.get(i1).size();i++) {
                        for(int j=0;j<v2.get(capnum).size();j++) {
                            int scn = v1.get(i1).get(i);
                            int cpn = v2.get(capnum).get(j);
                            g.get(scn).add(cpn);
                        }
                    }
                }

                while (!q.isEmpty()) {
                    Point cur = q.remove();
                    for (int k = 0; k < 4; k++) {
                        Point next = new Point(cur, k);
                        int num = scdist[cur.x][cur.y] + 1;
                        if (next.valid() && scdist[next.x][next.y] == -1 && sci[next.x][next.y] != 'Y' && sci[next.x][next.y] != 'Z' && (num <= zdist[next.x][next.y] || zdist[next.x][next.y] == -1) && num <= t) {
                            if (zdist[next.x][next.y] != num) {
                                scdist[next.x][next.y] = num;
                                q.add(next);
                            }
                            if (p[next.x][next.y] >= 0) {
                                int capnum = p[next.x][next.y];
                                for(int i=0;i<v1.get(i1).size();i++) {
                                    for(int j=0;j<v2.get(capnum).size();j++) {
                                        int scn = v1.get(i1).get(i);
                                        int cpn = v2.get(capnum).get(j);
                                        g.get(scn).add(cpn);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            pair1 = new int[numsci];
            pair2 = new int[numcaps];
            for(int i=0;i<numsci;i++) {
                pair1[i] = -1;
            }
            for(int i=0;i<numcaps;i++) {
                pair2[i] = -1;
            }
            for(int i=0;i<numsci;i++) {
                used = new boolean[numsci];
                find(i);
            }

            int count = 0;
            for(int i=0;i<numsci;i++) {
                if (pair1[i] != -1)
                    count++;
            }
            out.printf("%d", count);

            br.close();
            out.close();
            reader.close();
            writer.close();
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
        finally {
        }
    }

    private boolean find(int v) {
        used[v] = true;
        boolean result = false;
        ArrayList<Integer> list = g.get(v);
        for(int i : list) {
            if (pair2[i] == -1 || (!used[pair2[i]] && find(pair2[i]))) {
                result = true;
                pair1[v] = i;
                pair2[i] = v;
                break;
            }
        }
        return result;
    }

    public static void main(String[] args) {
        ProblemE f = new ProblemE();
        f.solve();
    }

    private class MyTokenizer {
        private String s;
        private int cur;

        public MyTokenizer(String s) {
            this.s = s;
            cur = 0;
        }

        public void skip() {
            while (cur < s.length() && (s.charAt(cur) == ' ' || s.charAt(cur) == '\t' || s.charAt(cur) == '\n')) {
                cur++;
            }
        }

        public double getDouble() {
            skip();
            String snum = "";
            while (cur < s.length() && (s.charAt(cur) >= '0' && s.charAt(cur) <= '9' || s.charAt(cur) == '.' || s.charAt(cur) == '-')) {
                snum += s.charAt(cur);
                cur++;
            }
            if (snum.startsWith("."))
                snum = "0" + snum;
            return Double.valueOf(snum);
        }

        public int getInteger() {
            skip();
            String snum = "";
            while (cur < s.length() && (s.charAt(cur) >= '0' && s.charAt(cur) <= '9' || s.charAt(cur) == '.' || s.charAt(cur) == '-')) {
                snum += s.charAt(cur);
                cur++;
            }
            return Integer.valueOf(snum);
        }

        public String getString() {
            skip();
            String s2 = "";
            while (cur < s.length() && (((s.charAt(cur) >= 'a' && s.charAt(cur) <= 'z')) ||
                    ((s.charAt(cur) >= 'A' && s.charAt(cur) <= 'Z')) ||
                    ((s.charAt(cur) >= '0' && s.charAt(cur) <= '9')) ||
                    s.charAt(cur) == '_'
            )) {
                s2 += s.charAt(cur);
                cur++;
            }
            return s2;
        }

        public char getCurrentChar() throws Exception {
            if (cur < s.length())
                return s.charAt(cur);
            else
                throw new Exception("Current character out of string length");
        }

        public void moveNextChar() {
            if (cur < s.length())
                cur++;
        }

        public boolean isFinished() {
            return cur >= s.length();
        }
    }
}


import java.io.*;
import java.util.*;
import java.math.*;

public class E implements Runnable {

	void solve() {
		int n = nextInt();
		int t = nextInt();
		char[][] c = new char[n][];
		for (int i = 0; i < n; i++) {
			c[i] = nextToken().toCharArray();
		}
		int[][] infectTime = new int[n][n];
		for (int i = 0; i < n; i++) {
			Arrays.fill(infectTime[i], Integer.MAX_VALUE);
		}
		Queue<State> q = new ArrayDeque<State>();
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (c[i][j] == 'Z') {
					q.add(new State(i, j));
					infectTime[i][j] = 0;
				}
			}
		}
		while (!q.isEmpty()) {
			State state = q.poll();
			for (int dir = 0; dir < 4; dir++) {
				int x = state.x + DX[dir];
				int y = state.y + DY[dir];
				if (x < 0 || y < 0 || x >= n || y >= n || c[x][y] == 'Y'
						|| infectTime[x][y] != Integer.MAX_VALUE) {
					continue;
				}
				infectTime[x][y] = infectTime[state.x][state.y] + 1;
				q.add(new State(x, y));
			}
		}
		int[][][][] dist = new int[n][n][][];
		for (int i = 0; i < n; i++) {
			// System.err.println(Arrays.toString(infectTime[i]));
			for (int j = 0; j < n; j++) {
				dist[i][j] = findDists(n, c, i, j, infectTime);
			}
		}
		Graph g = new Graph(1 + n * n + n * n + 1);
		int sink = 1 + 2 * n * n;
		int shiftCapsule = 1 + n * n;
		int shiftMen = 1;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (c[i][j] != '0' && c[i][j] != 'Y' && c[i][j] != 'Z') {
					g.addEdge(0, i * n + j + shiftMen, 0, c[i][j] - '0');
				}
			}
		}
		char[][] capsule = new char[n][];
		for (int i = 0; i < n; i++) {
			capsule[i] = nextToken().toCharArray();
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (capsule[i][j] != '0' && capsule[i][j] != 'Y'
						&& capsule[i][j] != 'Z') {
					g.addEdge(i * n + j + shiftCapsule, sink, 0,
							capsule[i][j] - '0');
				}
			}
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				for (int k = 0; k < n; k++) {
					for (int k2 = 0; k2 < n; k2++) {
						if (dist[i][j][k][k2] <= t) {
							g.addEdge(i * n + j + shiftMen, k * n + k2
									+ shiftCapsule, 0, 1 << 20);
						}
					}
					// System.err.println(Arrays.toString(dist[i][j][k]));
				}
				// System.err.println();
			}
		}
		out.println(g.getMaxFlow(0, sink));
	}

	static int[][] findDists(int n, char[][] c, int startX, int startY,
			int[][] infectTime) {
		if (c[startX][startY] == 'Y' || c[startX][startY] == 'Z') {
			return new int[n][n];
		}
		Queue<State> q = new ArrayDeque<State>();
		int[][] d = new int[n][n];
		for (int i = 0; i < n; i++) {
			Arrays.fill(d[i], Integer.MAX_VALUE);
		}
		q.add(new State(startX, startY));
		d[startX][startY] = 0;
		while (!q.isEmpty()) {
			State state = q.poll();
			for (int dir = 0; dir < 4; dir++) {
				int x = state.x + DX[dir];
				int y = state.y + DY[dir];
				int newD = d[state.x][state.y] + 1;
				if (x < 0 || y < 0 || x >= n || y >= n || c[x][y] == 'Y'
						|| c[x][y] == 'Z' || d[x][y] != Integer.MAX_VALUE
						|| newD >= infectTime[x][y]) {
					continue;
				}
				d[x][y] = newD;
				q.add(new State(x, y));
			}
		}
		int[][] e = new int[n][];
		for (int i = 0; i < n; i++) {
			e[i] = d[i].clone();
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (d[i][j] == Integer.MAX_VALUE) {
					continue;
				}
				for (int dir = 0; dir < 4; dir++) {
					int x = i + DX[dir];
					int y = j + DY[dir];
					if (x < 0 || y < 0 || x >= n || y >= n || c[x][y] == 'Y'
							|| c[x][y] == 'Z') {
						continue;
					}
					if (d[i][j] + 1 == infectTime[x][y]
							&& d[i][j] + 1 < e[x][y]) {
						e[x][y] = d[i][j] + 1;
					}
				}
			}
		}
		return e;
	}

	static int[] DX = { 1, 0, -1, 0 };
	static int[] DY = { 0, 1, 0, -1 };

	static class State {
		int x;
		int y;

		public State(int x, int y) {
			super();
			this.x = x;
			this.y = y;
		}

	}

	static class Edge {
		int from;
		int to;
		int flow;
		int cap;
		Edge rev;

		public Edge(int from, int to, int flow, int cap) {
			super();
			this.from = from;
			this.to = to;
			this.flow = flow;
			this.cap = cap;
		}

	}

	static class Graph {
		ArrayList<Edge>[] edges;
		int[] cur;
		int[] q;
		int[] d;
		int n;

		public Graph(int n) {
			edges = new ArrayList[n];
			this.n = n;
			for (int i = 0; i < edges.length; i++) {
				edges[i] = new ArrayList<Edge>();
			}
		}

		void addEdge(int from, int to, int flow, int cap) {
			Edge e1 = new Edge(from, to, flow, cap);
			Edge e2 = new Edge(to, from, -flow, 0);
			e1.rev = e2;
			e2.rev = e1;
			edges[from].add(e1);
			edges[to].add(e2);
		}

		boolean bfs(int source, int target) {
			int head = 0;
			int tail = 1;
			Arrays.fill(d, Integer.MAX_VALUE);
			d[source] = 0;
			q[0] = source;
			while (head < tail) {
				int x = q[head++];
				for (Edge e : edges[x]) {
					if (e.cap - e.flow > 0 && d[e.to] == Integer.MAX_VALUE) {
						d[e.to] = d[x] + 1;
						q[tail++] = e.to;
						if (e.to == target) {
							return true;
						}
					}
				}
			}
			return false;
		}

		int dfs(int x, int target, int cMin) {
			if (x == target) {
				return cMin;
			}
			for (int i = cur[x]; i < edges[x].size(); cur[x] = ++i) {
				Edge e = edges[x].get(i);
				if (d[e.to] != d[x] + 1 || e.cap - e.flow == 0) {
					continue;
				}
				int add = dfs(e.to, target, Math.min(cMin, e.cap - e.flow));
				if (add == 0) {
					continue;
				}
				e.flow += add;
				e.rev.flow -= add;
				return add;
			}
			return 0;
		}

		long getMaxFlow(int source, int target) {
			cur = new int[n];
			q = new int[n];
			d = new int[n];
			long flow = 0;
			while (bfs(source, target)) {
				Arrays.fill(cur, 0);
				while (true) {
					int add = dfs(source, target, Integer.MAX_VALUE);
					if (add == 0) {
						break;
					}
					flow += add;
				}
			}
			return flow;
		}
	}

	FastScanner sc;
	PrintWriter out;

	public void run() {
		Locale.setDefault(Locale.US);
		try {
			sc = new FastScanner(System.in);
			out = new PrintWriter(System.out);
			solve();
			sc.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	int nextInt() {
		return sc.nextInt();
	}

	String nextToken() {
		return sc.nextToken();
	}

	long nextLong() {
		return sc.nextLong();
	}

	double nextDouble() {
		return sc.nextDouble();
	}

	BigInteger nextBigInteger() {
		return sc.nextBigInteger();
	}

	class FastScanner extends BufferedReader {
		StringTokenizer st;
		boolean eof;
		String buf;
		String curLine;
		boolean createST;

		public FastScanner(String fileName) throws FileNotFoundException {
			this(fileName, true);
		}

		public FastScanner(String fileName, boolean createST)
				throws FileNotFoundException {
			super(new FileReader(fileName));
			this.createST = createST;
			nextToken();
		}

		public FastScanner(InputStream stream) {
			this(stream, true);
		}

		public FastScanner(InputStream stream, boolean createST) {
			super(new InputStreamReader(stream));
			this.createST = createST;
			nextToken();
		}

		String nextLine() {
			String ret = curLine;
			if (createST) {
				st = null;
			}
			nextToken();
			return ret;
		}

		String nextToken() {
			if (!createST) {
				try {
					curLine = readLine();
				} catch (Exception e) {
					eof = true;
				}
				return null;
			}
			while (st == null || !st.hasMoreTokens()) {
				try {
					curLine = readLine();
					st = new StringTokenizer(curLine);
				} catch (Exception e) {
					eof = true;
					break;
				}
			}
			String ret = buf;
			buf = eof ? "-1" : st.nextToken();
			return ret;
		}

		int nextInt() {
			return Integer.parseInt(nextToken());
		}

		long nextLong() {
			return Long.parseLong(nextToken());
		}

		double nextDouble() {
			return Double.parseDouble(nextToken());
		}

		BigInteger nextBigInteger() {
			return new BigInteger(nextToken());
		}

		public void close() {
			try {
				buf = null;
				st = null;
				curLine = null;
				super.close();
			} catch (Exception e) {

			}
		}

		boolean isEOF() {
			return eof;
		}
	}

	public static void main(String[] args) {
		new E().run();
	}
}


import java.util.*;

public class E
{
   public static void main(String[] args)
   {
      new E(new Scanner(System.in));
   }

   public E(Scanner in)
   {
      int N = in.nextInt();
      int T = in.nextInt();

      int[][] cnt = new int[N][N];
      int[][] grid = new int[N][N];

      // This is the gas start point
      vect start = null;
      // These are the scientists
      ArrayList<vect> vs = new ArrayList<vect>();
      for (int j=0; j<N; j++)
      {
         String s = in.next();
         for (int i=0; i<N; i++)
         {
            char c = s.charAt(i);
            if (Character.isDigit(c))
            {
               grid[i][j] = T;
               int v = (int)(c-'0');
               while (v-->0)
                  vs.add(new vect(i,j));
            }
            else if (c == 'Y')
               grid[i][j] = 0;
            else if (c == 'Z')
            {
               grid[i][j] = 0;
               start = new vect(i,j);
            }
         }
      }

      for (int j=0; j<N; j++)
      {
         String s = in.next();
         for (int i=0; i<N; i++)
         {
            char c = s.charAt(i);
            if (Character.isDigit(c))
            {
               int v = (int)(c-'0');
               cnt[i][j] = v;
            }
         }
      }

      // Flood fill bfs the grid from the start point
      ArrayDeque<Node> q = new ArrayDeque<Node>();
      q.add(new Node(start, 0));
      while (q.size() > 0)
      {
         Node cur = q.poll();
         vect v = cur.v;
         grid[v.x][v.y] = cur.d;

         int nd = cur.d+1;
         vect dv = new vect(1,0);
         for (int i=0; i<4; i++)
         {
            dv = dv.orthoCW();
            vect nv = v.add(dv);
            if (nv.x < 0)
               continue;
            if (nv.y < 0)
               continue;
            if (nv.x >= N)
               continue;
            if (nv.y >= N)
               continue;
            if (grid[nv.x][nv.y] <= nd)
               continue;
            q.add(new Node(nv, nd));
         }
      }

      /*for (int j=0; j<N; j++)
      {
         StringBuilder sb = new StringBuilder();
         for (int i=0; i<N; i++)
            sb.append(grid[i][j]+" ");
         System.out.println(sb);
      }*/

      // Create a maxflow graph for all reachable reactors
      MaxFlow solver = new MaxFlow(2+vs.size()+N*N, 0, 1);
      for (int i=0; i<vs.size(); i++)
         solver.add(0, 2+i, 1);
      for (int j=0; j<N; j++)
         for (int i=0; i<N; i++)
            solver.add(2+vs.size()+j*N+i, 1, cnt[i][j]);

      // BFS for all reachable reactors
      boolean[][] seen = new boolean[N][N];
      int u = 0;
      for (vect st : vs)
      {
         for (boolean[] see : seen)
            Arrays.fill(see, false);

         q.add(new Node(st, 0));
         while (q.size() > 0)
         {
            Node cur = q.poll();
            vect v = cur.v;
            if (seen[v.x][v.y])
               continue;
            if (cur.d > grid[v.x][v.y])
               continue;
            seen[v.x][v.y] = true;
            if (cur.d == grid[v.x][v.y])
               continue;

            int nd = cur.d+1;
            vect dv = new vect(1,0);
            for (int i=0; i<4; i++)
            {
               dv = dv.orthoCW();
               vect nv = v.add(dv);
               if (nv.x < 0)
                  continue;
               if (nv.y < 0)
                  continue;
               if (nv.x >= N)
                  continue;
               if (nv.y >= N)
                  continue;
               if (nd > grid[v.x][v.y])
                  continue;
               if (seen[nv.x][nv.y])
                  continue;
               q.add(new Node(nv, nd));
            }
         }

         for (int j=0; j<N; j++)
            for (int i=0; i<N; i++)
               if (seen[i][j])
                  solver.add(2+u, 2+vs.size()+j*N+i, 1);
         u++;
      }

      int res = solver.maxFlow();
      System.out.printf("%d%n", res);
   }
}

class vect
{
   int x, y;
   public vect(int i, int j)
   {
      x=i; y=j;
   }

   vect add(vect rhs)
   {
      return new vect(x+rhs.x, y+rhs.y);
   }

   vect orthoCW()
   {
      return new vect(-y, x);
   }
}

class Node
{
   vect v;
   int d;

   public Node(vect vv, int dd)
   {
      v=vv; d=dd;
   }
}

class MaxFlow
{
   int N, src, snk;
   ArrayList<Edge>[] adj;
   boolean[] seen;
   public MaxFlow(int N)
   {
      this.N = N;
      seen = new boolean[N];
      adj = new ArrayList[N];
      for (int i=0; i<N; i++)
         adj[i] = new ArrayList<Edge>();
   }

   public MaxFlow(int N, int src, int snk)
   {
      this(N);
      this.src = src;
      this.snk = snk;
   }

   void add(int u, int v, int c)
   {
      Edge e = new Edge(u, v, c);
      Edge r = new Edge(v, u, 0, c);
      r.back = true;
      e.rev = r; r.rev = e;
      adj[u].add(e);
      adj[v].add(r);
   }

   int maxFlow()
   {
      int ret = 0;
      while (true)
      {
         Arrays.fill(seen, false);
         int f = dfs(src, Integer.MAX_VALUE);
         if (f == 0) break;
         ret += f;
      }
      return ret;
   }

   int dfs(int cur, int aug)
   {
      if (cur == snk) return aug;
      if (seen[cur]) return 0;
      seen[cur] = true;

      for (Edge e : adj[cur])
         if (e.resid > 0 && !seen[e.v])
         {
            int a = dfs(e.v, Math.min(aug, e.resid));
            if (a > 0)
            {
               e.resid -= a;
               e.rev.resid += a;
               return a;
            }
         }
      return 0;
   }

   class Edge
   {
      int u, v, resid, cap;
      Edge rev;
      boolean back;
      public Edge(int uu, int vv, int cc)
      {
         u=uu; v=vv; cap = resid = cc;
      }
      public Edge(int uu, int vv, int rr, int cc)
      {
         this(uu, vv, cc); resid = rr;
      }
      int flow() { return cap-resid;}
   }
}


import java.util.Collections;
import java.util.InputMismatchException;
import java.math.BigInteger;
import java.util.Stack;
import java.util.*;
import java.util.Set;
import java.util.Collection;
import java.util.ArrayList;
import java.util.List;
import java.util.Comparator;
import java.io.*;
import java.util.Iterator;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.Arrays;

/**
 * Generated by Contest helper plug-in
 * Actual solution is at the bottom
 */
public class Main {
    public static void main(String[] args) {
        InputReader in = new StreamInputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);
        run(in, out);
    }

    public static void run(InputReader in, PrintWriter out) {
        Solver solver = new TaskE();
        solver.solve(1, in, out);
        Exit.exit(in, out);
    }
}

abstract class InputReader {
    private boolean finished = false;

    public abstract int read();

    public int readInt() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int res = 0;
        do {
            if (c < '0' || c > '9')
                throw new InputMismatchException();
            res *= 10;
            res += c - '0';
            c = read();
        } while (!isSpaceChar(c));
        return res * sgn;
    }

    public String readString() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        StringBuffer res = new StringBuffer();
        do {
            res.appendCodePoint(c);
            c = read();
        } while (!isSpaceChar(c));
        return res.toString();
    }

    private boolean isSpaceChar(int c) {
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public char readCharacter() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        return (char) c;
    }

    public void setFinished(boolean finished) {
        this.finished = finished;
    }

    public abstract void close();
}

class StreamInputReader extends InputReader {
    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar, numChars;

    public StreamInputReader(InputStream stream) {
        this.stream = stream;
    }

    public int read() {
        if (numChars == -1)
            throw new InputMismatchException();
        if (curChar >= numChars) {
            curChar = 0;
            try {
                numChars = stream.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar++];
    }

    @Override
    public void close() {
        try {
            stream.close();
        } catch (IOException ignored) {
        }
    }
}

class Exit {
    private Exit() {
    }

    public static void exit(InputReader in, PrintWriter out) {
        in.setFinished(true);
        in.close();
        out.close();
    }
}

interface Solver {
    public void solve(int testNumber, InputReader in, PrintWriter out);
}

class Pair<U, V> {

    public final U first;
    public final V second;

    public static<U, V> Pair<U, V> makePair(U first, V second) {
        return new Pair<U, V>(first, second);
    }

    private Pair(U first, V second) {
        this.first = first;
        this.second = second;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Pair pair = (Pair) o;

        return !(first != null ? !first.equals(pair.first) : pair.first != null) && !(second != null ? !second.equals(pair.second) : pair.second != null);

    }

    @Override
    public int hashCode() {
        int result = first != null ? first.hashCode() : 0;
        result = 31 * result + (second != null ? second.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "(" + first + "," + second + ")";
    }
}

interface Edge {
    public int getSource();
    public int getDestination();
    public long getCapacity();
    public void pushFlow(long flow);
    public Edge getReverseEdge();
}

class Graph {
    private final int size;
    private final List<Edge>[] edges;

    public Graph(int size) {
        this.size = size;
        //noinspection unchecked
        edges = new List[size];
        for (int i = 0; i < size; i++)
            edges[i] = new ArrayList<Edge>();
    }

    public int getSize() {
        return size;
    }

    public List<Edge> getIncident(int vertex) {
        return edges[vertex];
    }

    public void add(Edge edge) {
        edges[edge.getSource()].add(edge);
        edge = edge.getReverseEdge();
        if (edge != null)
            edges[edge.getSource()].add(edge);
    }

    }

class GraphAlgorithms {
    public static long dinic(Graph graph, int source, int destination) {
        long totalFlow = 0;
        int vertexCount = graph.getSize();
        int[] nextEdge = new int[vertexCount];
        while (true) {
            long[] distance = edgeDistances(graph, source).getDistances();
            if (distance[destination] == Long.MAX_VALUE)
                break;
            Arrays.fill(nextEdge, 0);
            totalFlow += dinicImpl(graph, source, destination, Long.MAX_VALUE, distance, nextEdge);
        }
        return totalFlow;
    }

    private static DistanceResult edgeDistances(Graph graph, int source) {
        int size = graph.getSize();
        Deque<Integer> queue = new ArrayDeque<Integer>(size);
        boolean[] processed = new boolean[size];
        boolean[] notReached = new boolean[size];
        Arrays.fill(notReached, true);
        long[] distance = new long[size];
        int[] last = new int[size];
        Arrays.fill(distance, Long.MAX_VALUE);
        distance[source] = 0;
        last[source] = -1;
        queue.add(source);
        notReached[source] = false;
        int iterationCount = 0;
        while (!queue.isEmpty()) {
            iterationCount++;
            if (iterationCount / size / size / size != 0)
                return null;
            int current = queue.poll();
            processed[current] = true;
            for (Edge edge : graph.getIncident(current)) {
                if (edge.getCapacity() == 0)
                    continue;
                int next = edge.getDestination();
                long weight = 1;
                if (distance[next] > distance[current] + weight) {
                    distance[next] = distance[current] + weight;
                    last[next] = current;
                    if (notReached[next]) {
                        notReached[next] = false;
                        queue.add(next);
                    } else if (processed[next]) {
                        processed[next] = false;
                        queue.addFirst(next);
                    }
                }
            }
        }
        return new DistanceResult(distance, last);
    }

    private static long dinicImpl(Graph graph, int source, int destination, long flow, long[] distance, int[] nextEdge) {
        if (source == destination)
            return flow;
        if (flow == 0 || distance[source] == distance[destination])
            return 0;
        List<Edge> incident = graph.getIncident(source);
        int incidentSize = incident.size();
        int totalPushed = 0;
        for (int i = nextEdge[source]; i < incidentSize; i++) {
            Edge edge = incident.get(i);
            int nextDestination = edge.getDestination();
            if (distance[nextDestination] != distance[source] + 1)
                continue;
            long pushed = dinicImpl(graph, nextDestination, destination, Math.min(flow, edge.getCapacity()),
                distance, nextEdge);
            if (pushed != 0) {
                edge.pushFlow(pushed);
                flow -= pushed;
                totalPushed += pushed;
                if (flow == 0) {
                    nextEdge[source] = i;
                    return totalPushed;
                }
            }
        }
        nextEdge[source] = incidentSize;
        return totalPushed;
    }

    public static class DistanceResult {
        private final long[] distances;
        private final int[] last;

        public DistanceResult(long[] distances, int[] last) {
            this.distances = distances;
            this.last = last;
        }

        public long[] getDistances() {
            return distances;
        }

        }

    }

class SimpleEdge implements Edge {
    protected final int source;
    protected final int destination;

    public SimpleEdge(int source, int destination) {
        this.source = source;
        this.destination = destination;
    }

    public int getSource() {
        return source;
    }

    public int getDestination() {
        return destination;
    }

    public long getCapacity() {
        return 0;
    }

    public void pushFlow(long flow) {
        throw new UnsupportedOperationException();
    }

    public Edge getReverseEdge() {
        return null;
    }

    }

class FlowEdge extends SimpleEdge {
    private long capacity;
    private long flow = 0;
    private Edge reverseEdge;

    public FlowEdge(int source, int destination, long capacity) {
        super(source, destination);
        this.capacity = capacity;
        reverseEdge = new ReverseEdge();
    }

    @Override
    public long getCapacity() {
        return capacity;
    }

    @Override
    public void pushFlow(long flow) {
        if (flow > 0) {
            if (this.capacity < flow)
                throw new IllegalArgumentException();
        } else {
            if (this.flow < -flow)
                throw new IllegalArgumentException();
        }
        capacity -= flow;
        this.flow += flow;
    }

    @Override
    public Edge getReverseEdge() {
        return reverseEdge;
    }

    private class ReverseEdge implements Edge {
        public int getSource() {
            return destination;
        }

        public int getDestination() {
            return source;
        }

        public long getCapacity() {
            return flow;
        }

        public void pushFlow(long flow) {
            FlowEdge.this.pushFlow(-flow);
        }

        public Edge getReverseEdge() {
            return FlowEdge.this;
        }
    }
}

class IOUtils {

    public static char[] readCharArray(InputReader in, int size) {
        char[] array = new char[size];
        for (int i = 0; i < size; i++)
            array[i] = in.readCharacter();
        return array;
    }

    public static char[][] readTable(InputReader in, int rowCount, int columnCount) {
        char[][] table = new char[rowCount][];
        for (int i = 0; i < rowCount; i++)
            table[i] = readCharArray(in, columnCount);
        return table;
    }

    }

class MiscUtils {
    public static final int[] DX_4_CONNECTED = {1, 0, -1, 0};
    public static final int[] DY_4_CONNECTED = {0, -1, 0, 1};

    }

class TaskE implements Solver {
    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int size = in.readInt();
        int time = in.readInt();
        char[][] scientists = IOUtils.readTable(in, size, size);
        char[][] rescue = IOUtils.readTable(in, size, size);
        Graph graph = new Graph(2 * size * size + 2);
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (Character.isDigit(scientists[i][j]))
                    graph.add(new FlowEdge(2 * size * size, i * size + j, scientists[i][j] - '0'));
                if (Character.isDigit(rescue[i][j]))
                    graph.add(new FlowEdge(size * size + i * size + j, 2 * size * size + 1, rescue[i][j] - '0'));
            }
        }
        int badRow = -1;
        int badColumn = -1;
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (rescue[i][j] == 'Z') {
                    badRow = i;
                    badColumn = j;
                }
            }
        }
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (Character.isDigit(scientists[i][j]) && scientists[i][j] != '0') {
                    if (rescue[i][j] != '0')
                        graph.add(new FlowEdge(i * size + j, size * size + i * size + j, Integer.MAX_VALUE));
                    Set<Pair<Integer, Integer>> canBe = new HashSet<Pair<Integer, Integer>>();
                    canBe.add(Pair.makePair(i, j));
                    Set<Pair<Integer, Integer>> caNtBe = new HashSet<Pair<Integer, Integer>>();
                    caNtBe.add(Pair.makePair(badRow, badColumn));
                    for (int k = 0; k < time; k++) {
                        Set<Pair<Integer, Integer>> nextCanBe = new HashSet<Pair<Integer, Integer>>();
                        for (Pair<Integer, Integer> cell : canBe) {
                            for (int l = 0; l < 4; l++) {
                                int newRow = cell.first + MiscUtils.DX_4_CONNECTED[l];
                                int newColumn = cell.second + MiscUtils.DY_4_CONNECTED[l];
                                if (newRow >= 0 && newColumn >= 0 && newRow < size && newColumn < size && Character.isDigit(scientists[newRow][newColumn])) {
                                    Pair<Integer, Integer> next = Pair.makePair(newRow, newColumn);
                                    if (!caNtBe.contains(next)) {
                                        if (rescue[newRow][newColumn] != '0')
                                            graph.add(new FlowEdge(i * size + j, size * size + newRow * size + newColumn, Integer.MAX_VALUE));
                                        nextCanBe.add(next);
                                    }
                                }
                            }
                        }
                        Set<Pair<Integer, Integer>> nextCaNtBe = new HashSet<Pair<Integer, Integer>>();
                        for (Pair<Integer, Integer> cell : caNtBe) {
                            nextCaNtBe.add(cell);
                            for (int l = 0; l < 4; l++) {
                                int newRow = cell.first + MiscUtils.DX_4_CONNECTED[l];
                                int newColumn = cell.second + MiscUtils.DY_4_CONNECTED[l];
                                if (newRow >= 0 && newColumn >= 0 && newRow < size && newColumn < size && Character.isDigit(scientists[newRow][newColumn])) {
                                    Pair<Integer, Integer> next = Pair.makePair(newRow, newColumn);
                                    nextCaNtBe.add(next);
                                }
                            }
                        }
                        canBe = nextCanBe;
                        caNtBe = nextCaNtBe;
                        canBe.removeAll(caNtBe);
                    }
                }
            }
        }
        out.println(GraphAlgorithms.dinic(graph, 2 * size * size, 2 * size * size + 1));
    }
}