#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
// 0
//1 3
// 2
struct position{
int x,y;
explicit operator bool(){
return x != -1;
}
position forward(int dir){
return position{x+(dir&1)*(dir-2), y+(!(dir&1))*(dir-1)};
}
bool operator==(const position& b) const{
return x == b.x && y == b.y;
}
void print(){
cout << y << ' ' << x << '\n';
}
};
class Board{
public:
vector<vector<int>> types;
vector<vector<vector<position>>> jumps;
int w, h;
vector<position> bots;
int nbBots;
Board(){}
Board(int _w, int _h, int _nbBots):
w(_w),
h(_h),
types(_h, vector<int>(_w)),
jumps(_h, vector<vector<position>>(_w, vector<position>(4, {-1, -1}))),
nbBots(_nbBots),
bots(_nbBots){}
void read(){
for(int y=0; y<h; y++){
string line;
getline(cin, line);
while(!line.size())getline(cin, line);
for(int x=0; x<w; x++){
if(isupper(line[x]))
types[y][x] = (line[x] == 'C')+1;
else if(isalpha(line[x]))
types[y][x] = 3;
else if(isdigit(line[x]))
bots[line[x]-'1'] = {x, y};
}
}
}
int changedir(position pos, int dir){
if(types[pos.y][pos.x] == 1)
return (dir+1)&3;
else if(types[pos.y][pos.x] == 2)
return (dir-1)&3;
return dir;
}
bool isvalid(position pos){
return
pos.x >= 0 && pos.x < w &&
pos.y >= 0 && pos.y < h &&
types[pos.y][pos.x] != 3;
}
position jump(position cur, int dir){
if((bool)jumps[cur.y][cur.x][dir]){
return jumps[cur.y][cur.x][dir];
}
vector<pair<position, int>> stack;
stack.push_back({cur, dir});
while(isvalid(cur.forward(dir))){
cur = cur.forward(dir);
dir = changedir(cur, dir);
}
assert(isvalid(cur));
for(auto state:stack){
jumps[state.first.y][state.first.x][state.second] = cur;
}
return cur;
}
};
int n, w, h;
int MAX;
Board board;
vector<vector<vector<int>>> fromStart;
void bfs(position pos, int id){
vector<pair<position, int>> Q(w*h);
int start = 0;
int end = 0;
Q[end++] = {pos, 0};
fromStart[id][pos.y][pos.x] = 0;
while(start < end){
auto cur = Q[start++];
for(int dir=0; dir<4; dir++){
position nextpos = board.jump(cur.first, dir);
if(fromStart[id][nextpos.y][nextpos.x] == MAX){
fromStart[id][nextpos.y][nextpos.x] = cur.second+1;
Q[end++] = {nextpos, cur.second+1};
}
}
}
}
vector<vector<int>> toGoal;
int dp(position pos, position end){
if(pos == end)return 0;
if(toGoal[pos.y][pos.x] != -1)return toGoal[pos.y][pos.x];
toGoal[pos.y][pos.x] = w*h;
for(int dir=0; dir<4; dir++){
int score = dp(pos, end);
toGoal[pos.y][pos.x] = min(toGoal[pos.y][pos.x], score);
}
return toGoal[pos.y][pos.x];
}
int main(){
cin >> n >> w >> h;
board = Board(w, h, n);
MAX = n*w*h;
board.read();
fromStart.resize(n, vector<vector<int>>(h, vector<int>(w, MAX)));
//board.jump(board.bots[1], 0).print();
//board.bots[1].forward(0).print();
for(int i=0; i<n; i++){
bfs(board.bots[i], i);
}
int res = w*h*n;
for(int y=0; y<h; y++){
for(int x=0; x<w; x++){
int score = 0;
for(int i=0; i<n; i++){
score += fromStart[i][y][x];
}
//cout << score << ' ';
res = min(res, score);
}
//cout << '\n';
}
cout << res << '\n';
}