#include <bits/stdc++.h>
#define rep(i,n) for(int i = 0; i < n; i++)
const int    INF = 100000000;
const double EPS = 1e-10;
const int    MOD = 1000000007;
using namespace std;
typedef pair<int,int> P;

int dh[4] = {0,1,0,-1};
int dw[4] = {1,0,-1,0};

int w, h, s;
int st, go;
char m[50][50], tmp[(1<<10)][50][50];
char ms[10][50][50];
int dp[(1<<10)*50*50*2+50*50*2+50*50+50];

int main(){
	rep(i,(1<<10)*50*50*2+50*50*2+50*50+50) dp[i] = INF;
	cin >> w >> h;
	rep(i,h) rep(j,w){
		cin >> m[i][j];
		if(m[i][j] == '%'){
			st = i*50+j;
			m[i][j] = '_';
		}
		if(m[i][j] == '&'){
			go = i*50+j;
			m[i][j] = '_';
		}
	}
	cin >> s;
	rep(i,s) rep(j,h) rep(k,w) cin >> ms[i][j][k];
	rep(i,(1<<s)){
		rep(j,h) rep(k,w) tmp[i][j][k] = m[j][k];
		int I = i;
		rep(j,s){
			if(I&1){
				rep(k,h) rep(l,w){
					if(ms[j][k][l] == '*'){
						if(tmp[i][k][l] == '_') tmp[i][k][l] = '^';
						else if(tmp[i][k][l] == '^') tmp[i][k][l] = '_';
						else if('a' <= tmp[i][k][l] && tmp[i][k][l] <= 'z'){
							tmp[i][k][l] = toupper(tmp[i][k][l]);
						} else{
							tmp[i][k][l] = tolower(tmp[i][k][l]);
						}
					}
				}
			}
			I >>= 1;
		}
	}
	queue<int> que;
	que.push(st);
	dp[st] = 0;
	while(!que.empty()){
		int q = que.front();
		que.pop();
		int i = q/(2*50*50), j = (q%(50*50))/50, k = q%50, f = (q%(2*50*50))/(50*50);
		if(tmp[i][j][k] == '#') continue;
		if(!f){
			rep(l,4){
				int J = j+dh[l], K = k+dw[l];
				if(0 > J || J >= h) continue;
				if(0 > K || K >= w) continue;
				if(tmp[i][J][K] == '|' || tmp[i][J][K] == '_' || ('a' <= tmp[i][J][K]&&tmp[i][J][K] <= 'z')){
					if(dp[i*2*50*50+50*J+K] != INF) continue;
					dp[i*2*50*50+50*J+K] = dp[q]+1;
					que.push(i*2*50*50+50*J+K);
				}
			}
			if(tmp[i][j][k] == '|' && dp[i*2*50*50+50*50+50*j+k] == INF){
				dp[i*2*50*50+50*50+50*j+k] = dp[q]+1;
				que.push(i*2*50*50+50*50+50*j+k);
			}
		}
		if(f){
			rep(l,4){
				int J = j+dh[l], K = k+dw[l];
				if(0 > J || J >= h) continue;
				if(0 > K || K >= w) continue;
				if(tmp[i][J][K] == '|' || tmp[i][J][K] == '^' || ('A' <= tmp[i][J][K]&&tmp[i][J][K] <= 'Z')){
					if(dp[i*2*50*50+50*50+50*J+K] != INF) continue;
					dp[i*2*50*50+50*50+50*J+K] = dp[q]+1;
					que.push(i*2*50*50+50*50+50*J+K);
				}
			}
			if(tmp[i][j][k] == '|' && dp[i*2*50*50+50*j+k] == INF){
				dp[i*2*50*50+50*j+k] = dp[q]+1;
				que.push(i*2*50*50+50*j+k);
			}
		}
		if(!f && 'a' <= tmp[i][j][k] && tmp[i][j][k] <= 'z'){
			int z = tmp[i][j][k]-'a';
			int flo = 0;
			if(ms[z][j][k] == '*') flo = 1;
			if(i&(1<<z)){
				if(dp[(i-(1<<z))*2*50*50+flo*50*50+50*j+k] == INF){
					dp[(i-(1<<z))*2*50*50+flo*50*50+50*j+k] = dp[q]+1;
					que.push((i-(1<<z))*2*50*50+flo*50*50+50*j+k);
				}
			} else{
				if(dp[(i+(1<<z))*2*50*50+flo*50*50+50*j+k] == INF){
					dp[(i+(1<<z))*2*50*50+flo*50*50+50*j+k] = dp[q]+1;
					que.push((i+(1<<z))*2*50*50+flo*50*50+50*j+k);
				}
			}
		}
		if(f && 'A' <= tmp[i][j][k] && tmp[i][j][k] <= 'Z'){
			int z = tmp[i][j][k] - 'A';
			int flo = 1;
			if(ms[z][j][k] == '*') flo = 0;
			if(i&(1<<z)){
				if(dp[(i-(1<<z))*2*50*50+flo*50*50+50*j+k] == INF){
					dp[(i-(1<<z))*2*50*50+flo*50*50+50*j+k] = dp[q]+1;
					que.push((i-(1<<z))*2*50*50+flo*50*50+50*j+k);
				}
			} else{
				if(dp[(i+(1<<z))*2*50*50+flo*50*50+50*j+k] == INF){
					dp[(i+(1<<z))*2*50*50+flo*50*50+50*j+k] = dp[q]+1;
					que.push((i+(1<<z))*2*50*50+flo*50*50+50*j+k);
				}
			}
		}
	}
	int ans = INF;
	rep(i,(1<<10)*50*50*2+50*50*2+50*50+50){
		if(i%(50*50) != go) continue;
		ans = min(ans,dp[i]);
	}
	if(ans == INF) ans = -1;
	cout << ans << endl;
}

Measured memory_bytes: 23908