#include <iostream>
#include <vector>
#include <string>
#include <cstring>

using namespace std;

bool wall[16*16];
int mv[] = {0, 1, -1, 16, -16};

int compress(int pa, int pb, int pc){
	return (pa)|(pb<<8)|(pc<<16);
}

int solve(int start, int goal){
	static bool visit[16*16*16*16*16*16];
	memset(visit, false, sizeof(visit));
	visit[start] = true;
	vector<int> state[2]; state[0].push_back(start);
	for(int res=1; ;res++){
		int cur = 1-res%2, next = res%2;
		state[next].clear();
		for(int i=0;i<state[cur].size();i++){
			int pa = state[cur][i]%256, pb = (state[cur][i]>>8)%256, pc = (state[cur][i]>>16);
			for(int a=0;a<5;a++){
				int npa = pa + mv[a];
				if(wall[npa]) continue;
				for(int b=0;b<(pb?5:1);b++){
					int npb = pb + mv[b];
					if(npb!=0){
						if(wall[npb]) continue;
						if(npa==npb) continue;
						if(npb==pa&&npa==pb) continue;
					}
					for(int c=0;c<(pc?5:1);c++){
						int npc = pc + mv[c];
						if(npc!=0){
							if(wall[npc]) continue;
							if(npc==npa||npc==npb) continue;
							if(npc==pa&&npa==pc) continue;
							if(npc==pb&&npb==pc) continue;
						}
						int ns = (npa)|(npb<<8)|(npc<<16);
						if(visit[ns]) continue;
						if(ns==goal) return res;
						visit[ns] = true;
						state[next].push_back(ns);						
					}
				}
			}
		}
	}
	return -1;
}

int main(){
	int w, h, n;
	string mp[16];
	while(cin >> w >> h >> n, w){
		getline(cin, mp[0]);
		for(int i=0;i<h;i++) getline(cin, mp[i]);
		memset(wall, false, sizeof(wall));
		int start = 0, goal = 0;
		for(int i=0;i<h;i++){
			for(int j=0;j<w;j++){
				if(mp[i][j]=='#') wall[16*i+j] = true;
				if(islower(mp[i][j])) start |= (16*i+j) << (8*(mp[i][j]-'a'));
				if(isupper(mp[i][j])) goal  |= (16*i+j) << (8*(mp[i][j]-'A'));
			}
		}
		printf("%d\n", solve(start, goal));
	}
}