#include<cstdio>
#include<algorithm>
#include<queue>
#include<math.h>
#include<string.h>
using namespace std;
const int dx[] = { -1, 1, 0, 0 };
const int dy[] = { 0, 0, -1, 1 };
int w, h, n;
int mymap[400][10];
int deg[400];
int ghost[4], target[4];
int *hash_table;
int *dist;
int pos_count;
queue<int> q1, q2;

int judge1(int org1, int org2, int aft1, int aft2) {
	if ((aft1 == aft2) || (org1 == aft2 && org2 == aft1))
		return 0;
	return 1;
}

int judge2(int parent, int child, int flag) {
	if (!hash_table[child]) {
		if (flag == 1)
			q1.push(child);
		else
			q2.push(child);

		hash_table[child] = flag;
		dist[child] = dist[parent] + 1;
	}
	else if (hash_table[child] != flag) {
		int result = dist[parent] + 1 + dist[child];
		printf("%d\n", result);
		return 1;
	}
	return 0;
}

int search(int parent, int p1, int p2, int p3, int flag) {
	for (int d1 = 0; d1 < deg[p1]; d1++) {
		int c1 = mymap[p1][d1];
		if (n == 1 && judge2(parent, c1, flag))
			return 1;
		else if (n > 1) {
			for (int d2 = 0; d2 < deg[p2]; d2++) {
				int c2 = mymap[p2][d2];
				if (!judge1(p1, p2, c1, c2))
					continue;
				if (n == 2 && judge2(parent, c1 + pos_count * c2, flag))
					return 1;
				else if (n == 3) {
					for (int d3 = 0; d3 < deg[p3]; d3++) {
						int c3 = mymap[p3][d3];
						if (!(judge1(p1, p3, c1, c3) && judge1(p2, p3, c2, c3)))
							continue;
						if (judge2(parent, c1 + pos_count * c2 + pos_count * pos_count * c3, flag))
							return 1;
					}
				}
			}
		}
	}
	return 0;
}

int bfs() {
	int status1 = ghost[0] + ghost[1] * pos_count + ghost[2] * pos_count*pos_count;
	int status2 = target[0] + target[1] * pos_count + target[2] * pos_count*pos_count;
	q1 = queue<int>();
	q2 = queue<int>();
	q1.push(status1);
	q2.push(status2);
	hash_table[status1] = 1;
	hash_table[status2] = 2;
	dist[status1] = 0;
	dist[status2] = 0;
	int layer_count = 0;
	while (!q1.empty() || !q2.empty()) {
		while (!q1.empty() && (dist[status1] == layer_count)) {
			status1 = q1.front();
			int status11 = status1 % pos_count;
			int status12 = status1 / pos_count % pos_count;
			int status13 = status1 / pos_count / pos_count % pos_count;
			q1.pop();
			if (search(status1, status11, status12, status13, 1))
				return 1;
		}
		while (!q2.empty() && (dist[status2] == layer_count)) {
			status2 = q2.front();
			int status21 = status2 % pos_count;
			int status22 = status2 / pos_count % pos_count;
			int status23 = status2 / pos_count / pos_count % pos_count;
			q2.pop();
			if (search(status2, status21, status22, status23, 2))
				return 1;
		}
		layer_count++;
	}
	return -1;
}

void init() {
	for (int i = 0; i < 400; i++)
		deg[i] = 0;
}

int main() {
	while (scanf("%d%d%d", &w, &h, &n) == 3 && n) {
		char map[20][20];
		int map2[20][20];
		memset(ghost, 0, sizeof(ghost));
		memset(target, 0, sizeof(target));
		memset(map2, -1, sizeof(map2));

		pos_count = 0;
		for (int i = 0; i <= h; i++) {

			fgets(map[i], 20, stdin);
			if (i) {
				for (int j = 0; j < w; j++) {
					if (map[i][j] != '#') {
						///printf("%d\t", map[i][j]);
						mymap[pos_count][0] = pos_count;
						if (map[i][j] >= 97 && map[i][j] <= 99) {
							ghost[map[i][j] % 97] = pos_count;
						}
						else if (map[i][j] >= 65 && map[i][j] <= 67)
							target[map[i][j] % 65] = pos_count;
						map2[i][j] = pos_count;
						pos_count++;
					}
				}
			}
		}

		int pos_count2 = 0;
		for (int i = 1; i <= h; i++) {
			for (int j = 0; j < w; j++) {
				int degree = 1;
				if (map2[i][j] != -1) {
					for (int k = 0; k < 4; k++) {
						int nx = i + dx[k];
						int ny = j + dy[k];
						if (map2[nx][ny] != -1) {
							int space_index = map2[nx][ny];
							mymap[pos_count2][degree++] = space_index;
						}
					}
					deg[pos_count2++] = degree;
				}
			}
		}

		int size = 1;
		for (int i = 0; i < n; i++)
			size *= pos_count;
		hash_table = new int[size];
		dist = new int[size];
		for (int i = 0; i < size; i++) {
			hash_table[i] = 0;
			dist[i] = -1;
		}

		bfs();

		delete[] hash_table;
		delete[] dist;
	}
}


Measured memory_bytes: 18156