#include <bits/stdc++.h>
using namespace std;
const int maxn = 16 + 10, maxm = 192 + 10;
int cx[] = { -1, 1, 0, 0, 0}, cy[] = {0, 0, -1, 1, 0}, w, h, n, cnt;
int id[maxn][maxn], G[maxm][5], st[3], ed[3], edge[maxm], d[maxm][maxm][maxm];
struct ghost
{
int a, b, c;
ghost(int aa, int bb, int cc): a(aa), b(bb), c(cc) {}
};
inline bool ok(int a, int b, int a1, int b1)
{
return ((a1 == b1) || (a1 == b && b1 == a));
}
void bfs()
{
queue<ghost>q;
q.push(ghost(st[0], st[1], st[2]));
d[st[0]][st[1]][st[2]] = 0;
while (!q.empty())
{
ghost u = q.front(); q.pop();
if (u.a == ed[0] && u.b == ed[1] && u.c == ed[2]) return;
for (int i = 1, a1 = G[u.a][i]; i <= edge[u.a]; ++i, a1 = G[u.a][i])
for (int j = 1, b1 = G[u.b][j]; j <= edge[u.b]; ++j, b1 = G[u.b][j])
if (!ok(u.a, u.b, a1, b1))
for (int k = 1, c1 = G[u.c][k]; k <= edge[u.c]; c1 = G[u.c][k], ++k, c1 = G[u.c][k])
if (!(ok(u.a, u.c, a1, c1) || ok(u.b, u.c, b1, c1)) && d[a1][b1][c1] == -1)
{
d[a1][b1][c1] = d[u.a][u.b][u.c] + 1;
q.push(ghost(a1, b1, c1));
}
}
}
int main(int argc, char const * argv[])
{
char M[maxn][maxn];
ios::sync_with_stdio(false);
while (cin >> w >> h >> n && n)
{
cnt = 0;
int x[maxm], y[maxm];
memset(edge, 0, sizeof(edge));
memset(d, -1, sizeof(d));
cin.get(); cin.get();
for (int i = 0; i < h; i++)
cin.getline(M[i], 20);
for (int i = 0; i < h; i++)
for (int j = 0; j < w; j++)
if (M[i][j] != '#')
{
id[i][j] = ++cnt;//利用矩阵存储稀疏图 , cnt为每个节点的编号
x[cnt] = i, y[cnt] = j;
if ('a' <= M[i][j] && M[i][j] <= 'c')
st[M[i][j] - 'a'] = cnt;//找到起始点
if ('A' <= M[i][j] && M[i][j] <= 'C')
ed[M[i][j] - 'A'] = cnt;//找到终止点
}
for (int i = 1; i <= cnt; i++)
for (int j = 0; j < 5; j++)//使用edge存储第i个节点具有的相邻节点数
if (M[x[i] + cx[j]][y[i] + cy[j]] != '#')//遍历五个方向,寻找每个节点的相邻节点
G[i][++edge[i]] = id[x[i] + cx[j]][y[i] + cy[j]];//第五个是自身
for (int i = 2; i > 0; i--)
if (n <= i)
{
edge[++cnt] = 1;
G[cnt][1] = cnt;
st[i] = ed[i] = cnt;
}//补充虚拟节点,在判断非法情况是起作用
bfs();
cout << d[ed[0]][ed[1]][ed[2]] << endl;
}
return 0;
}
学这道题,花费了我大量的精力,题目真是相当经典