#include<bits/stdc++.h>
using namespace std;

using Field=vector<string>;

const int N=3;
using P=pair<int,int>;
using Ps=array<P,N>;

const int SIZE=18;
const int DP_SIZE=SIZE*SIZE*SIZE*SIZE*SIZE*SIZE;
const int D=5;
const int dh[]={0,1,0,-1,0};
const int dw[]={0,0,1,0,-1};

array<short,DP_SIZE> dp;
Ps sp,tp;

void init(int h,int w){
    for(int i=0;i<N;i++) sp[i]=tp[i]={h,w};
    fill(dp.begin(),dp.end(),1e9);
}
int encode(P& x){return x.first+x.second*SIZE;}
int encode(Ps& x){ return encode(x[0])+SIZE*SIZE*encode(x[1])+SIZE*SIZE*SIZE*SIZE*encode(x[2]);}
Ps decode(int x){
    int r=1;
    Ps res;
    for(int i=0;i<3;i++){
        res[i]={x/r%SIZE,x/r/SIZE%SIZE};
        r*=SIZE*SIZE;
    }
    return res;
}
int solve(int w,int h,int n,Field f){
    init(h,w);
    for(int i=0;i<h;i++){
        for(int j=0;j<w;j++){
            if(isupper(f[i][j])){
                tp[f[i][j]-'A']={i,j};
            }
            else if(islower(f[i][j])){
                sp[f[i][j]-'a']={i,j};
            }
        }
    }
    
    vector<vector<vector<int>>> est(N,vector<vector<int>>(h+1,vector<int>(w+1,3*(SIZE*SIZE+2))));
    
    for(int i=0;i<3;i++){
        est[i][tp[i].first][tp[i].second]=0;
        queue<pair<int,int>> que;
        while(!que.empty()){
            auto p=que.front(); que.pop();
            int x=p.first,y=p.second;
            if(f[x][y]=='#') continue;
            for(int j=1;j<D;j++){
                int tox=x+dh[j],toy=dw[j];
                if(tox<h && toy<w && est[i][tox][toy]!=SIZE*SIZE+2){
                    est[i][tox][toy]=est[i][x][y]+1;
                    que.push({tox,toy});
                }
            }
        }
    }
    
    using Item=pair<short,int>;
    priority_queue<Item,vector<Item>,greater<Item>> que;
    auto hf=[&](Ps& p){
        int res=0;
        for(int i=0;i<N;i++) res=max(res,est[i][p[i].first][p[i].second]);
        return res;
    };
    auto push=[&](Ps& p,int d){
        int hv=encode(p);
        if(d<dp[hv]){
            dp[hv]=d;
            int dest=d+hf(p);
            que.push({d+hf(p),hv});
        }
    };
    auto isRange=[&](Ps& p,Ps& pre){
        for(int i=0;i<N;i++){
            if(!(p[i].first==h && p[i].second==w || p[i].first<h && p[i].second<w && f[p[i].first][p[i].second]!='#')) return false;
        }
        for(int i=0;i<N;i++){
            for(int j=0;j<i;j++){
                if(p[i].first==h || p[j].first==h) continue;
                if(p[i]==p[j]) return false;
                if(p[i]==pre[j] && p[j]==pre[i]) return false;
            }
        }
        return true;
    };
    auto trans=[&](Ps& p,int hv){
        Ps np;
        for(int i=0;i<D;i++){
            np[0]={p[0].first+dh[i],p[0].second+dw[i]};
            for(int j=0;j<D;j++){
                np[1]={p[1].first+dh[j],p[1].second+dw[j]};
                for(int k=0;k<D;k++){
                    np[2]={p[2].first+dh[k],p[2].second+dw[k]};
                    if(isRange(np,p)){
                        push(np,dp[hv]+1);
                    }
                }
            }
        }
    };
    auto debug=[&](Ps& p){
        cerr<<"$Debug begin."<<endl;
        for(int i=0;i<3;i++){
            cerr<<p[i].first<<" "<<p[i].second<<endl;
        }  
        cerr<<"$Debug end."<<endl;
    };
    push(sp,0);
    while(!que.empty()){
        auto ret=que.top(); que.pop();
        int hv=ret.second;
        Ps p=decode(hv);
        if(ret.first>dp[hv]+hf(p)) continue;
        // debug(p);
        if(p==tp) return ret.first;
        trans(p,hv);
    }
    throw std::runtime_error("Unexpected");
}
int main(){
    int w,h,n;
    while(cin>>w>>h>>n,w){
        string buf;
        getline(cin,buf);
        Field f(h);
        for(int i=0;i<h;i++){
            getline(cin,f[i]);
        }
        cout<<solve(w,h,n,f)<<endl;
    }
    return 0;
}


Measured memory_bytes: 71316