Problem:
Problem G:
The Morning after Halloween
You are working for an amusement park as an operator of an
obakeyashiki
, or a haunted house,
in which guests walk through narrow and dark corridors. The house is proud of their lively
ghosts, which are actually robots remotely controlled by the operator, hiding here and there in
the corridors. One morning, you found that the ghosts are not in the positions where they are
supposed to be. Ah, yesterday was Halloween. Believe or not, paranormal spirits have moved
them around the corridors in the night. You have to move them into their right positions before
guests come. Your manager is eager to know how long it takes to restore the ghosts.
In this problem, you are asked to write a program that, given a floor map of a house, finds the
smallest number of steps to move all ghosts to the positions where they are supposed to be.
A floor consists of a matrix of square cells. A cell is either a wall cell where ghosts cannot move
into or a corridor cell where they can.
At each step, you can move any number of ghosts simultaneously. Every ghost can either stay
in the current cell, or move to one of the corridor cells in its 4-neighborhood (i.e. immediately
left, right, up or down), if the ghosts satisfy the following conditions:
No more than one ghost occupies one position at the end of the step.
No pair of ghosts exchange their positions one another in the step.
For example, suppose ghosts are located as shown in the following (partial) map, where a sharp sign ('
#
) represents a wall cell and 'a', 'b', and 'c' ghosts.
####
                                                  ab#
                                                 #c##
                                                 ####
The following four maps show the only possible positions of the ghosts after one step.
####      ####     ####     ####
                                    ab#      a b#     acb#     ab #
                                   #c##      #c##     # ##     #c##
                                   ####      ####     ####     ####
Input
The input consists of at most 10 datasets, each of which represents a floor map of a house. The format of a dataset is as follows.
w h n
c
11
c
12
...
c
1
w
c
21
c
22
...
c
2
w
. . ..       .
..           .
          .
..           .
c
h
1
c
h
2
...
c
h
w
w
,
h
and
n
in the first line are integers, separated by a space.
w
and
h
are the floor width
and height of the house, respectively.
n
is the number of ghosts. They satisfy the following constraints.
4 ≤
w
≤ 16
4 ≤
h
≤ 16
1 ≤
n
≤ 3
Subsequent
h
lines of
w
characters are the floor map. Each of
c
ij
is either:
a '
#
' representing a wall cell,
a lowercase letter representing a corridor cell which is the initial position of a ghost,
an uppercase letter representing a corridor cell which is the position where the ghost corresponding to its lowercase letter is supposed to be, or
a space representing a corridor cell that is none of the above.
In each map, each of the fir
...(truncated)

Submitted solutions:

code_snippet: #include<cstdio>
#include<cstring>
#include<cctype>
#include<queue>
using namespace std;

const int maxs = 20;
const int maxn = 150;
const int dx[]= {1,-1,0,0,0};
const int dy[]= {0,0,1,-1,0};

inline int ID(int a, int b, int c)
{
    return (a<<16)|(b<<8)|c;
}

int s[3], t[3];

int deg[maxn], G[maxn][5];

inline bool conflict(int a, int b, int a2, int b2)
{
    return a2 == b2 || (a2 == b && b2 == a);
}

int d[maxn][maxn][maxn];

int bfs()
{
    queue<int> q;
    memset(d, -1, sizeof(d));
    q.push(ID(s[0], s[1], s[2]));
    d[s[0]][s[1]][s[2]] = 0;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        int a = (u>>16)&0xff, b = (u>>8)&0xff, c = u&0xff;
        if(a == t[0] && b == t[1] && c == t[2]) return d[a][b][c];
        for(int i = 0; i < deg[a]; i++)
        {
            int a2 = G[a][i];
            for(int j = 0; j < deg[b]; j++)
            {
                int b2 = G[b][j];
                if(conflict(a, b, a2, b2)) continue;
                for(int k = 0; k < deg[c]; k++)
                {
                    int c2 = G[c][k];
                    if(conflict(a, c, a2, c2)) continue;
                    if(conflict(b, c, b2, c2)) continue;
                    if(d[a2][b2][c2] != -1) continue;
                    d[a2][b2][c2] = d[a][b][c]+1;
                    q.push(ID(a2, b2, c2));
                }
            }
        }
    }
    return -1;
}

int main()
{
    int w, h, n;

    while(scanf("%d%d%d\n", &w, &h, &n) == 3 && n)
    {
        char maze[20][20];
        for(int i = 0; i < h; i++)
            fgets(maze[i], 20, stdin);

        int cnt, x[maxn], y[maxn], id[maxs][maxs];
        cnt = 0;
        for(int i = 0; i < h; i++)
            for(int j = 0; j < w; j++)
                if(maze[i][j] != '#')
                {
                    x[cnt] = i;
                    y[cnt] = j;
                    id[i][j] = cnt;
                    if(islower(maze[i][j])) s[maze[i][j] - 'a'] = cnt;
                    else if(isupper(maze[i][j])) t[maze[i][j] - 'A'] = cnt;
                    cnt++;
                }

        for(int i = 0; i < cnt; i++)
        {
            deg[i] = 0;
            for(int dir = 0; dir < 5; dir++)
            {
                int nx = x[i]+dx[dir], ny = y[i]+dy[dir];
                if(maze[nx][ny] != '#') G[i][deg[i]++] = id[nx][ny];
            }
        }

        if(n <= 2)
        {
            deg[cnt] = 1;
            G[cnt][0] = cnt;
            s[2] = t[2] = cnt++;
        }
        if(n <= 1)
        {
            deg[cnt] = 1;
            G[cnt][0] = cnt;
            s[1] = t[1] = cnt++;
        }

        printf("%d\n", bfs());
    }
    return 0;
}
accuracy: 1
time_ms: 510
memory_kb: 16688
final_rank: 2

code_snippet: #include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node{
	int x,y,p;
};
struct nodenode{
	int x,y,xx,yy,p,typ;
};
struct nodenodenode{
	int x,y,xx,yy,xxx,yyy,p,typ;
};
int n,m,x;
char s[55][55];
int dx[5]={1,0,-1,0,0},
	dy[5]={0,1,0,-1,0};
void solve1(){
	int sx=0,sy=0,ex=0,ey=0;
	for(int i=1;i<=n;i++){
		char c=getchar();
		for(int j=1;j<=m;j++){
			s[i][j]=getchar();
			if(s[i][j]=='a')sx=i,sy=j;
			if(s[i][j]=='A')ex=i,ey=j;
		}
	}
	
	queue<node>q;
	q.push({sx,sy,0});
	bool vis[22][22]={};
	while(!q.empty()){
		auto qwe=q.front(); q.pop();
		int x=qwe.x,y=qwe.y,p=qwe.p;
		if(x==ex&&y==ey){
			cout<<p<<"\n";
			return ;
		}
		vis[x][y]=1;
		for(int i=0;i<4;i++){
			int xx=dx[i]+x,yy=dy[i]+y;
			if(xx<1||xx>n||yy<1||yy>m||s[xx][yy]=='#'||vis[xx][yy])
				continue;
			vis[xx][yy]=1;
			q.push({xx,yy,p+1});
		}
	}
}

void solve2(){
	int qx=0,qy=0,wx=0,wy=0,ex=0,ey=0,fx=0,fy=0;
	for(int i=1;i<=n;i++){
		char c=getchar();
		for(int j=1;j<=m;j++){
			s[i][j]=getchar();
			if(s[i][j]=='a')qx=i,qy=j;
			if(s[i][j]=='A')wx=i,wy=j;
			if(s[i][j]=='b')ex=i,ey=j;
			if(s[i][j]=='B')fx=i,fy=j;
		}
	}
	
	queue<nodenode>q;
	q.push({qx,qy,ex,ey,0,1});
	q.push({wx,wy,fx,fy,0,2});
	short vis[22][22][22][22]={};
	short d[22][22][22][22]={};
	vis[qx][qy][ex][ey]=1;
	vis[wx][wy][fx][fy]=2;
	while(!q.empty()){
		auto qwe=q.front(); q.pop();
		int x=qwe.x,y=qwe.y,xx=qwe.xx,yy=qwe.yy,p=qwe.p,typ=qwe.typ;
		
		for(int i=0;i<5;i++){
			for(int j=0;j<5;j++){
				int ax=dx[i]+x,ay=dy[i]+y;
				int bx=dx[j]+xx,by=dy[j]+yy;
				if(ax<1||ax>n||ay<1||ay>m||s[ax][ay]=='#')continue;
				if(bx<1||bx>n||by<1||by>m||s[bx][by]=='#')continue;
				if(ax==bx&&ay==by)continue;
				if(ax==xx&&ay==yy&&bx==x&&by==y)continue;
				if(vis[ax][ay][bx][by]==typ)continue;
				if(vis[ax][ay][bx][by]+typ==3){
					cout<<d[ax][ay][bx][by]+d[x][y][xx][yy]+1<<"\n";
					return ;
				}
				vis[ax][ay][bx][by]=typ;
				d[ax][ay][bx][by]=d[x][y][xx][yy]+1;
				q.push({ax,ay,bx,by,p+1,typ});
			}
		}
	}
}

void solve3(){
	int ax=0,ay=0,bx=0,by=0,cx=0,cy=0,ex=0,ey=0,fx=0,fy=0,gx=0,gy=0;
	for(int i=1;i<=n;i++){
		char c=getchar();
		for(int j=1;j<=m;j++){
			s[i][j]=getchar();
			if(s[i][j]=='a')ax=i,ay=j;
			if(s[i][j]=='A')bx=i,by=j;
			if(s[i][j]=='b')cx=i,cy=j;
			if(s[i][j]=='B')ex=i,ey=j;
			if(s[i][j]=='c')fx=i,fy=j;
			if(s[i][j]=='C')gx=i,gy=j;
		}
	}
	
	queue<nodenodenode>q;
	q.push({ax,ay,cx,cy,fx,fy,0,1});
	q.push({bx,by,ex,ey,gx,gy,0,2});
	short vis[17][17][17][17][17][17]={};
	short d[17][17][17][17][17][17]={};
	vis[ax][ay][cx][cy][fx][fy]=1;
	vis[bx][by][ex][ey][gx][gy]=2;
	while(!q.empty()){
		auto qwe=q.front(); q.pop();
		int x=qwe.x,y=qwe.y,xx=qwe.xx,yy=qwe.yy,
			xxx=qwe.xxx,yyy=qwe.yyy,p=qwe.p,typ=qwe.typ;
//		cout<<x<<" "<<y<<" "<<xx<<" "<<yy<<" "<<xxx<<" "<<yyy<<"\n";
//		cout<<d[x][y][xx][yy][xxx][yyy]<<"\n";
//		cout<<x<<" "<<y<<" "<<xx<<" "<<yy<<" "<<xxx<<" "<<yyy<<" "<<p<<"\n";
//		char r[22][22]={};
//		for(int i=1;i<=n;i++)
//			for(int j=1;j<=m;j++){
//				r[i][j]=s[i][j];
//				if(r[i][j]>='A'&&r[i][j]<='z')r[i][j]=' ';
//			}
//		r[x][y]='a',r[xx][yy]='b',r[xxx][yyy]='c';
//		for(int i=1;i<=n;i++){
//			for(int j=1;j<=m;j++)cout<<r[i][j];
//			cout<<"\n";
//		}
//		
//		if(x==bx&&y==by&&xx==ex&&yy==ey&&xxx==gx&&yyy==gy){
//			cout<<p<<"\n";
//			return ;
//		}
		for(int i=0;i<5;i++){
			int X=dx[i]+x,Y=dy[i]+y;
			if(X<1||X>n||Y<1||Y>m||s[X][Y]=='#')continue;
			for(int j=0;j<5;j++){
				int XX=dx[j]+xx,YY=dy[j]+yy;
				if(XX<1||XX>n||YY<1||YY>m||s[XX][YY]=='#')continue;
				if(X==xx&&Y==yy&&XX==x&&YY==y)continue;
				if(X==XX&&Y==YY)continue;
				for(int w=0;w<5;w++){
					int XXX=dx[w]+xxx,YYY=dy[w]+yyy;
					if(XXX<1||XXX>n||YYY<1||YYY>m||s[XXX][YYY]=='#')continue;
					if(X==xxx&&Y==yyy&&XXX==x&&YYY==y)continue;
					if(XX==xxx&&YY==yyy&&XXX==xx&&YYY==yy)continue;
					if(XX==XXX&&YY==YYY)continue;
					if(X==XXX&&Y==YYY)continue;
					if(vis[X][Y][XX][YY][XXX][YYY]==typ)continue;
					if(vis[X][Y][XX][YY][XXX][YYY]+typ==3){
						cout<<d[X][Y][XX][YY][XXX][YYY]+
								d[x][y][xx][yy][xxx][yyy]+1<<"\n";
						return ;
					}
					vis[X][Y][XX][YY][XXX][YYY]=typ;
					d[X][Y][XX][YY][XXX][YYY]=
							d[x][y][xx][yy][xxx][yyy]+1;
					q.push({X,Y,XX,YY,XXX,YYY,p+1,typ});
				}
			}
		}
	}
}

signed main(){
//	freopen("halloween.in","r",stdin);
//	freopen("halloween.out","w",stdout);
//	ios::sync_with_stdio(0);
//	cin.tie(0);
	while(1){
		cin>>m>>n>>x;
		if(n==0)return 0;
		if(x==1)solve1();
		if(x==2)solve2();
		if(x==3)solve3();
	}
}
accuracy: 1
time_ms: 1090
memory_kb: 99580
final_rank: 13

code_snippet: #include <cstdio>
#include <vector>
#include <algorithm>
#include <array>
#include <queue>
using namespace std;
using i64 = long long;
#define rep(i,n) for(i64 i=0; i<(i64)(n); i++)

int dist[300][300][300];

int solve(int w, int z, int n, vector<int> pos0, vector<int> pos1, vector<int> G){
    rep(i,z) rep(j,z) rep(k,z) dist[i][j][k] = -1;
    int dx[5] = { 0,-1,1,-w,w };
    dist[pos0[0]][pos0[1]][pos0[2]] = 0;
    queue<array<int,3>> que; que.push({ pos0[0], pos0[1], pos0[2] });
    while(que.size()){
        auto [a,b,c] = que.front(); que.pop();
        for(int da:dx){
            int nxa = a + da;
            if(G[nxa] != 1) continue;
            for(int db:dx){
                int nxb = b + db;
                if(G[nxb] != 1) continue;
                if(n!=1) if(nxb==nxa || (a==nxb && b==nxa)) continue;
                for(int dc:dx){
                    int nxc = c + dc;
                    if(G[nxc] != 1) continue;
                    if(dist[nxa][nxb][nxc] != -1) continue;
                    if(n<=2 || (nxb!=nxc && nxc!=nxa && !(a==nxc && c==nxa) && !(c==nxb && b==nxc))){
                        dist[nxa][nxb][nxc] = dist[a][b][c] + 1;
                        que.push({ nxa, nxb, nxc });
                    }
                }
            }
        }
    }
    return dist[pos1[0]][pos1[1]][pos1[2]];
}

void testcase(){
    int w, h, n; scanf("%d%d%d", &w, &h, &n);
    if(w == 0) exit(0);
    vector<int> G;
    vector<int> pos0(n);
    vector<int> pos1(n);
    rep(y,h){
        scanf(" ");
        rep(x,w){
            char c; scanf("%c", &c);
            G.push_back(c == '#' ? 0 : 1);
            if('a' <= c && c <= 'c') pos1[c-'a'] = y*w+x;
            if('A' <= c && c <= 'C') pos0[c-'A'] = y*w+x;
        }
    }
    rep(ss,3-n){ pos0.push_back(h*w-w); pos1.push_back(h*w-w); }
    G.push_back(0); G[h*w-w] = 1;
    int ans = solve(w, h*w+1, n, pos0, pos1, G);
    printf("%d\n", ans);
}

int main(){
    while(true) testcase();
    return 0;
}
accuracy: 1
time_ms: 1100
memory_kb: 96508
final_rank: 12

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int dx[5] = {-16,-1,0,1,16};
int encode(int X, int Y) {return X*16+Y;}

int main() {
while(1) {
    int N, M, K;
    cin >> M >> N >> K;
    if (N == 0) return 0;
    bool G[256] = {};
    rep(i,0,256) G[i] = false;
    vector<pair<char,int>> s, t;
    string _;
    getline(cin,_);
    rep(i,0,N) {
        getline(cin,_);
        rep(j,0,M) {
            char C = _[j];
            if (C != '#') G[encode(i,j)] = true;
            if ('a' <= C && C <= 'z') s.push_back({C,encode(i,j)});
            if ('A' <= C && C <= 'Z') t.push_back({C,encode(i,j)});
        }
    }
    sort(ALL(s)), sort(ALL(t));
    vector<int> S(K), T(K);
    rep(i,0,K) S[i] = s[i].second, T[i] = t[i].second;
    if (K == 1) {
        static int DP[256] = {};
        rep(i,0,256) DP[i] = inf;
        queue<int> Q;
        DP[S[0]] = 0, Q.push(S[0]);
        while(!Q.empty()) {
            int V = Q.front();
            Q.pop();
            rep(i,0,5) {
                int NV = V + dx[i];
                if (G[NV]) {
                    if (chmin(DP[NV],DP[V]+1)) {
                        Q.push(NV);
                    }
                }
            }
        }
        cout << DP[T[0]] << endl;
    }
    if (K == 2) {
        static int DP[256][256] = {};
        rep(i,0,256) rep(j,0,256) DP[i][j] = inf;
        queue<pair<int,int>> Q;
        DP[S[0]][S[1]] = 0, Q.push({S[0],S[1]});
        while(!Q.empty()) {
            auto [V1,V2] = Q.front();
            Q.pop();
            rep(i,0,5) {
                int NV1 = V1 + dx[i];
                if (!G[NV1]) continue;
                rep(j,0,5) {
                    int NV2 = V2 + dx[j];
                    if (!G[NV2]) continue;
                    if (NV1 == NV2) continue;
                    if ((NV1 == V2) && (NV2 == V1)) continue;
                    if (chmin(DP[NV1][NV2], DP[V1][V2] + 1)) {
                        Q.push({NV1,NV2});
                    }
                }
            }
        }
        cout << DP[T[0]][T[1]] << endl;
    }
    if (K == 3) {
        static int DP[256][256][256] = {};
        rep(i,0,256) rep(j,0,256) rep(k,0,256) DP[i][j][k] = inf;
        queue<tuple<int,int,int>> Q;
        DP[S[0]][S[1]][S[2]] = 0, Q.push({S[0],S[1],S[2]});
        while(!Q.empty()) {
            auto [V1,V2,V3] = Q.front();
            Q.pop();
            rep(i,0,5) {
                int NV1 = V1 + dx[i];
                if (!G[NV1]) continue;
                rep(j,0,5) {
                    int NV2 = V2 + dx[j];
                    if (!G[NV2]) continue;
                    if (NV1 == NV2) continue;
                    if ((NV1 == V2) && (NV2 == V1)) continue;
                    rep(k,0,5) {
                        int NV3 = V3 + dx[k];
                        if (!G[NV3]) continue;
                        if (NV1 == NV3) continue;
                        if ((NV1 == V3) && (NV3 == V1)) continue;
                        if (NV2 == NV3) continue;
                        if ((NV2 == V3) && (NV3 == V2)) continue;
                        if (chmin(DP[NV1][NV2][NV3],DP[V1][V2][V3]+1)) {
                            Q.push({NV1,NV2,NV3});
                        }
                    }
                }
            }
        }
        cout << DP[T[0]][T[1]][T[2]] << endl;
    }
}
}
accuracy: 1
time_ms: 1460
memory_kb: 71744
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int N = 17;

char a[N][N];
int h, w, n;
int dist[N * N][N * N][N * N];
vector<int> to[N * N];

inline bool check(int x, int x1, int y, int y1, int z, int z1) {
    if (y == 0 && z == 0)
        return true;
    if (x1 == y1 || x1 == z1 || z1 == y1)
        return false;
    if (x == y1 && y == x1)
        return false;
    if (x == z1 && x1 == z)
        return false;
    if (y == z1 && y1 == z)
        return false;
    return true;
}

int bfs(vector<int> &start, vector<int> fin) {
    deque<vector<int>> q;
    q.emplace_back(start);
    dist[start[0]][start[1]][start[2]] = 0;
    while (!q.empty()) {
        int x = q.front()[0], y = q.front()[1], z = q.front()[2];
        q.pop_front();
        for (auto x1 : to[x]) {
            for (auto y1 : to[y]) {
                for (auto z1 : to[z]) {
                    if (dist[x1][y1][z1] != -1 || (n > 1 && !check(x, x1, y, y1, z, z1)))
                        continue;
                    dist[x1][y1][z1] = dist[x][y][z] + 1;
                    vector<int> vec;
                    vec.emplace_back(x1);
                    vec.emplace_back(y1);
                    vec.emplace_back(z1);
                    q.emplace_back(vec);
                }
            }
        }
    }
    return dist[fin[0]][fin[1]][fin[2]];
}

void solve() {
    string input;
    while (true) {
        getline(cin, input);
        for (int i = 0; i < N * N; i++) {
            for (int j = 0; j < N * N; j++) {
                for (int z = 0; z < N * N; z++) {
                    dist[i][j][z] = -1;
                }
            }
        }

        for (int i = 0; i < N * N; i++) {
            to[i].clear();
        }


        string s;
        vector<int> pars;
        for (auto it : input) {
            if (it == ' ') {
                pars.emplace_back(stoi(s));
                s = "";
            }
            else
                s += it;
        }
        pars.emplace_back(stoi(s));
        w = pars[0], h = pars[1], n = pars[2];
        if (h == 0)
            break;
        for (int i = 0; i < h; i++) {
            getline(cin, input);
            for (int j = 0; j < w; j++) {
                a[i][j] = input[j];
            }
        }
        int cnt = 1;
        vector<vector<int>> num(h, vector<int> (w));    
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                num[i][j] = cnt++;
            }
        }
        to[0] = {0};
        vector<pair<int, int>> dif;
        dif.emplace_back(-1, 0);
        dif.emplace_back(1, 0);
        dif.emplace_back(0, 0);
        dif.emplace_back(0, -1);
        dif.emplace_back(0, 1);
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                for (auto it : dif) {
                    int dx = it.first, dy = it.second;
                    if (i + dx < 0 || i + dx >= h || j + dy < 0 || j + dy >= w || a[i + dx][j + dy] == '#')
                        continue;
                    to[num[i][j]].emplace_back(num[i + dx][j + dy]);
                }
            }
        }
        map<char, int> map_start, map_finish;
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                if (islower(a[i][j])) {
                    map_start[a[i][j]] = num[i][j];
                }
                if (isupper(a[i][j])) {
                    map_finish[a[i][j]] = num[i][j];
                }
            }
        }
        vector<int> start, fin;
        for (auto it : map_start)
            start.emplace_back(it.second);
        for (auto it : map_finish)
            fin.emplace_back(it.second);
        while (start.size() < 3)
            start.emplace_back(0);
        while (fin.size() < 3)
            fin.emplace_back(0);
        cout << bfs(start, fin) << endl;
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
}
accuracy: 1
time_ms: 1460
memory_kb: 111588
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define eb emplace_back
const int N = 17;

char a[N][N];
int h, w, n;
int dist[N * N][N * N][N * N];
vector<int> to[N * N];

inline bool check(int x, int x1, int y, int y1, int z, int z1) {
    if (y == 0 && z == 0)
        return true;
    if (x1 == y1 || x1 == z1 || z1 == y1)
        return false;
    if (x == y1 && y == x1)
        return false;
    if (x == z1 && x1 == z)
        return false;
    if (y == z1 && y1 == z)
        return false;
    return true;
}

int bfs(vector<int> &start, vector<int> fin) {
    deque<vector<int>> q;
    q.eb(start);
    dist[start[0]][start[1]][start[2]] = 0;
    while (!q.empty()) {
        int x = q.front()[0], y = q.front()[1], z = q.front()[2];
        q.pop_front();
        for (auto x1 : to[x]) {
            for (auto y1 : to[y]) {
                for (auto z1 : to[z]) {
                    if (dist[x1][y1][z1] != -1 || (n > 1 && !check(x, x1, y, y1, z, z1)))
                        continue;
                    dist[x1][y1][z1] = dist[x][y][z] + 1;
                    vector<int> vec = {x1, y1, z1};
                    q.eb(vec);
                }
            }
        }
    }
    return dist[fin[0]][fin[1]][fin[2]];
}

void solve() {
    string input;
    while (true) {
        getline(cin, input);
        for (int i = 0; i < N * N; i++) {
            for (int j = 0; j < N * N; j++) {
                for (int z = 0; z < N * N; z++) {
                    dist[i][j][z] = -1;
                }
            }
        }

        for (int i = 0; i < N * N; i++) {
            to[i].clear();
        }


        string s;
        vector<int> pars;
        for (auto it : input) {
            if (it == ' ') {
                pars.eb(stoi(s));
                s = "";
            }
            else
                s += it;
        }
        pars.eb(stoi(s));
        w = pars[0], h = pars[1], n = pars[2];
        if (h == 0)
            break;
        for (int i = 0; i < h; i++) {
            getline(cin, input);
            for (int j = 0; j < w; j++) {
                a[i][j] = input[j];
            }
        }
        int cnt = 1;
        vector<vector<int>> num(h, vector<int> (w));    
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                num[i][j] = cnt++;
            }
        }
        to[0] = {0};
        vector<pair<int, int>> dif = {{-1, 0}, {1, 0}, {0, 0}, {0, -1}, {0, 1}};
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                for (auto it : dif) {
                    int dx = it.first, dy = it.second;
                    if (i + dx < 0 || i + dx >= h || j + dy < 0 || j + dy >= w || a[i + dx][j + dy] == '#')
                        continue;
                    to[num[i][j]].eb(num[i + dx][j + dy]);
                }
            }
        }
        map<char, int> map_start, map_finish;
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                if (islower(a[i][j])) {
                    map_start[a[i][j]] = num[i][j];
                }
                if (isupper(a[i][j])) {
                    map_finish[a[i][j]] = num[i][j];
                }
            }
        }
        vector<int> start, fin;
        for (auto it : map_start)
            start.eb(it.second);
        for (auto it : map_finish)
            fin.eb(it.second);
        while (start.size() < 3)
            start.eb(0);
        while (fin.size() < 3)
            fin.eb(0);
        cout << bfs(start, fin) << endl;
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
}
accuracy: 1
time_ms: 960
memory_kb: 111460
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define eb emplace_back
const int N = 17;

char a[N][N];
int h, w, n;
int dist[N * N][N * N][N * N];
vector<int> to[N * N];

inline bool check(int x, int x1, int y, int y1, int z, int z1) {
    if (y == 0 && z == 0)
        return true;
    if (x1 == y1 || x1 == z1 || z1 == y1)
        return false;
    if (x == y1 && y == x1)
        return false;
    if (x == z1 && x1 == z)
        return false;
    if (y == z1 && y1 == z)
        return false;
    return true;
}

int bfs(vector<int> &start, vector<int> fin) {
    deque<vector<int>> q;
    q.eb(start);
    dist[start[0]][start[1]][start[2]] = 0;
    while (!q.empty()) {
        int x = q.front()[0], y = q.front()[1], z = q.front()[2];
        q.pop_front();
        for (auto x1 : to[x]) {
            for (auto y1 : to[y]) {
                for (auto z1 : to[z]) {
                    if (dist[x1][y1][z1] != -1 || (n > 1 && !check(x, x1, y, y1, z, z1)))
                        continue;
                    dist[x1][y1][z1] = dist[x][y][z] + 1;
                    vector<int> vec = {x1, y1, z1};
                    q.eb(vec);
                }
            }
        }
    }
    return dist[fin[0]][fin[1]][fin[2]];
}

void solve() {
    string input;
    while (true) {
        getline(cin, input);
        for (int i = 0; i < N * N; i++) {
            for (int j = 0; j < N * N; j++) {
                for (int z = 0; z < N * N; z++) {
                    dist[i][j][z] = -1;
                }
            }
        }

        for (int i = 0; i < N * N; i++) {
            to[i].clear();
        }


        string s;
        vector<int> pars;
        for (auto it : input) {
            if (it == ' ') {
                pars.eb(stoi(s));
                s = "";
            }
            else
                s += it;
        }
        pars.eb(stoi(s));
        w = pars[0], h = pars[1], n = pars[2];
        if (h == 0)
            break;
        for (int i = 0; i < h; i++) {
            getline(cin, input);
            for (int j = 0; j < w; j++) {
                a[i][j] = input[j];
            }
        }
        int cnt = 1;
        vector<vector<int>> num(h, vector<int> (w));    
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                num[i][j] = cnt++;
            }
        }
        to[0] = {0};
        vector<pair<int, int>> dif = {{-1, 0}, {1, 0}, {0, 0}, {0, -1}, {0, 1}};
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                for (auto [dx, dy] : dif) {
                    if (i + dx < 0 || i + dx >= h || j + dy < 0 || j + dy >= w || a[i + dx][j + dy] == '#')
                        continue;
                    to[num[i][j]].eb(num[i + dx][j + dy]);
                }
            }
        }
        map<char, int> map_start, map_finish;
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                if (islower(a[i][j])) {
                    map_start[a[i][j]] = num[i][j];
                }
                if (isupper(a[i][j])) {
                    map_finish[a[i][j]] = num[i][j];
                }
            }
        }
        vector<int> start, fin;
        for (auto it : map_start)
            start.eb(it.second);
        for (auto it : map_finish)
            fin.eb(it.second);
        while (start.size() < 3)
            start.eb(0);
        while (fin.size() < 3)
            fin.eb(0);
        cout << bfs(start, fin) << endl;
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
}
accuracy: 1
time_ms: 960
memory_kb: 111620
final_rank: 18

code_snippet: // #pragma GCC target("avx2")
#pragma GCC optimization("O3")
#pragma GCC optimization("unroll-loops")

#include <array>
#include <bitset>
#include <cmath>
#include <ios>
#include <iostream>
#include <queue>

using namespace std;

const int inf = 2e9;

int main() {
#ifdef erytw
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    auto decode = [](int pos) {
        return array<int, 3>{pos & ((1 << 8) - 1), (pos >> 8) & ((1 << 8) - 1),
                             (pos >> 16) & ((1 << 8) - 1)};
    };

    auto encode = [](array<int, 3> coords) {
        return coords[0] | (coords[1] << 8) | (coords[2] << 16);
    };

    int w, h, n;
    array<int, 1 << 24> dist;
    array<int, 3> start, finish;
    bitset<1 << 24> used, renewed;
    bitset<1 << 8> avaliable;

    array<int, 5> steps{0, 1, (1 << 4), -1, -(1 << 4)};
    auto stepvar = [&](int pos) {
        vector<int> step_list;

        return step_list;
    };

    string line;
    while (cin >> w >> h >> n) {
        if ((w | h | n) == 0) break;

        getline(cin, line);

        avaliable.set();
        used.reset();
        renewed.reset();
        start = finish = {0, 0, 0};

        for (int y = 0; y < h; ++y) {
            getline(cin, line);
            for (int x = 0; x < w; ++x) {
                if (line[x] == '#')
                    avaliable[x | (y << 4)] = false;
                else if (line[x] - 'A' < 3)
                    finish[line[x] - 'A'] = x | (y << 4);
                else if (line[x] - 'a' < 3)
                    start[line[x] - 'a'] = x | (y << 4);
            }
        }

        int spos = encode(start), fpos = encode(finish);

        queue<int> q;
        q.push(spos);
        dist[spos] = 0;
        renewed[spos] = 1;

        while (!q.empty()) {
            int pos = q.front();
            q.pop();
            used[pos] = true;

            if (pos == fpos) break;

            auto [a, b, c] = decode(pos);

            for (int step_a : steps) {
                for (int step_b : steps) {
                    for (int step_c : steps) {
                        if ((step_a | (n >= 2 ? step_b : 0) | (n >= 3 ? step_c : 0)) == 0)
                            continue;

                        int n_a = a + step_a, n_b = b + (n >= 2 ? step_b : 0),
                            n_c = c + (n >= 3 ? step_c : 0);

                        if (!avaliable[n_a] || n >= 2 && !avaliable[n_b] ||
                            n >= 3 && !avaliable[n_c])
                            continue;
                        if (n >= 2 && n_a == n_b ||
                            (n >= 3 && (n_a == n_c || n_b == n_c)))
                            continue;
                        if ((n >= 2 && a == n_b && b == n_a) ||
                            (n >= 3 &&
                             ((a == n_c && c == n_a) || (b == n_c && c == n_b))))
                            continue;

                        int npos = encode({n_a, n_b, n_c});
                        if (!renewed[npos]) {
                            dist[npos] = inf;
                            renewed[npos] = true;
                        }
                        if (dist[npos] > dist[pos] + 1) {
                            dist[npos] = dist[pos] + 1;
                            if (used[npos]) continue;
                            q.push(npos);
                        }
                    }
                }
            }
        }
        cout << dist[fpos] << '\n';
    }
}
accuracy: 1
time_ms: 3710
memory_kb: 68356
final_rank: 16

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

int solve(int w, int h, int n) {
    vector<string> g(h, string(w, '?'));
    vector<pair<int,int>> src(n, {-1, -1}), dst(n, {-1, -1});
    cin.ignore();
    for(int i = 0; i < h; i++) {
        string s; getline(cin, s);
        assert((int)s.size() == w);
        for(int j = 0; j < w; j++) {
            if(s[j] == '#') g[i][j] = '#';
            else if(s[j] == ' ') g[i][j] = '.';
            else {
                g[i][j] = '.';
                if(isupper(s[j])) {
                    src[s[j] - 'A'] = {i, j};
                } else {
                    dst[s[j] - 'a'] = {i, j};
                }
            }
        }
    }

    auto encode = [&](vector<pair<int,int>>& state) {
        int res = 0;
        for(int i = 0; i < n; i++) res = res * h * w + (state[i].first * w + state[i].second);  
        return res;
    };

    auto decode = [&](int v) {
        vector<pair<int,int>> state;
        for(int i = 0; i < n; i++) {
            const int q = v % w; v /= w;
            const int p = v % h; v /= h;
            state.push_back({p, q});
        }
        reverse(state.begin(), state.end());
        return state;
    };

    const int sz = pow(h * w, n);
    const int INF = 1e9;
    vector dist(sz, INF);
    queue<int> q;
    dist[encode(src)] = 0;
    q.push(encode(src));
    int goal = encode(dst);

    const int dx[] = {0, 0, +1, 0, -1};
    const int dy[] = {0, +1, 0, -1, 0};
    while(not q.empty()) {
        const int u = q.front(); q.pop();
        vector<pair<int,int>> now = decode(u);
        vector<pair<int,int>> now_ = now;

        auto dfs = [&](auto self, vector<pair<int,int>>& pos, int i) -> void {
            if(i == n) {
                const int v = encode(pos);
                if(dist[v] != INF) return;
                for(int k = 0; k < n; k++) {
                    for(int l = k + 1; l < n; l++) {
                        if(pos[k] == pos[l]) return;
                        if(pos[l] == now[k] and pos[k] == now[l]) return;
                    }
                }
                dist[v] = dist[u] + 1;
                q.push(v);
                return;
            }

            for(int d = 0; d < 5; d++) {
                if(g[pos[i].first + dx[d]][pos[i].second + dy[d]] == '.') {
                    pos[i].first  += dx[d];
                    pos[i].second += dy[d];
                    self(self, pos, i + 1);
                    pos[i].first  -= dx[d];
                    pos[i].second -= dy[d];
                }
            }
        }; dfs(dfs, now_, 0);
    }
    return dist[encode(dst)];
}

int main() {
    while(true) {
        int w, h, n; cin >> w >> h >> n; if(make_tuple(w, h, n) == make_tuple(0, 0, 0)) return 0;
        int answer = solve(w, h, n);
        cout << answer << endl;
    }
}
accuracy: 1
time_ms: 3230
memory_kb: 69848
final_rank: 14

code_snippet: #include <cctype>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
unsigned short vis[1 << 24];
char c[16][20];
bool wall[256];
int tm0;
inline bool check(int u, int v) {
  for (int i = 0; i < 24; i += 8) {
    int p1 = v >> i & 255;
    if (p1) {
      int j = i == 16 ? 0 : i + 8;
      int p2 = (v >> j % 24) & 255;
      int uShiftedJ = u >> j % 24 & 255;
      int uShiftedI = u >> i % 24 & 255;
      if (wall[p1] || p1 == p2 || (p1 == uShiftedJ && p2 == uShiftedI)) {
        return false;
      }
    }
  }
  return true;
}
int solve(int start, int goal) {
  const int dif[5] = {0, -1, 1, -16, 16};
  queue<int> q;
  q.push(start);
  q.push(-1);
  int tm = tm0 + 1;
  vis[start] = tm;
  while (1) {
    int u = q.front();
    q.pop();
    if (u < 0) {
      q.push(-1);
      ++tm;
    } else {
      for (int i1 = u & 255 ? 4 : 0; i1 >= 0; --i1)
        for (int i2 = u >> 8 & 255 ? 4 : 0; i2 >= 0; --i2)
          for (int i3 = u >> 16 ? 4 : 0; i3 >= 0; --i3) {
            int v = u + dif[i1] + (dif[i2] << 8) + (dif[i3] << 16);
            if (vis[v] <= tm0) {
              if (check(u, v)) {
                if (v == goal) {
                  return tm;
                }
                vis[v] = tm;
                q.push(v);
              }
            }
          }
    }
  }
}
int main() {
  int w, h;
  while (scanf("%d%d%*d ", &w, &h), w) {
    for (int i = 0; i < h; ++i) {
      fgets(c[i], 20, stdin);
    }
    int goal = 0;
    int start = 0;
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        if (c[i][j] == '#') {
          wall[i << 4 | j] = true;
        } else {
          wall[i << 4 | j] = false;
          if (isupper(c[i][j])) {
            goal |= (i << 4 | j) << (c[i][j] - 'A') * 8;
          } else if (islower(c[i][j])) {
            start |= (i << 4 | j) << (c[i][j] - 'a') * 8;
          }
        }
      }
    }
    int tm = solve(start, goal);
    printf("%d\n", tm - tm0);
    tm0 = tm + 1;
    if (tm0 > 55000) {
      memset(vis, 0, sizeof vis);
      tm0 = 0;
    }
  }
}
accuracy: 1
time_ms: 6460
memory_kb: 25524
final_rank: 15

code_snippet: #include <cctype>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
unsigned short vis[1 << 24];
char c[16][20];
bool wall[256];
int tm0;
inline bool check(int u, int v) {
  for (int i = 0; i < 24; i += 8) {
    int p1 = v >> i & 255;
    if (p1) {
      int j = i == 16 ? 0 : i + 8;
      if (wall[p1]) {
        return false;
      }
      int p2 = (v >> j % 24) & 255;
      int u_shift_j = (u >> j % 24 & 255);
      int u_shift_i = (u >> i % 24 & 255);
      if (p1 == p2 || (p1 == u_shift_j && p2 == u_shift_i)) {
        return false;
      }
    }
  }
  return true;
}
int solve(int start, int goal) {
  const int dif[5] = {0, -1, 1, -16, 16};
  queue<int> q;
  q.push(start);
  q.push(-1);
  int tm = tm0 + 1;
  vis[start] = tm;
  while (1) {
    int u = q.front();
    q.pop();
    if (u < 0) {
      q.push(-1);
      ++tm;
    } else {
      for (int i1 = u & 255 ? 4 : 0; i1 >= 0; --i1) {
        int v_i1 = dif[i1];
        for (int i2 = u >> 8 & 255 ? 4 : 0; i2 >= 0; --i2) {
          int v_i2 = dif[i2] << 8;
          for (int i3 = u >> 16 ? 4 : 0; i3 >= 0; --i3) {
            int v = u + v_i1 + v_i2 + (dif[i3] << 16);
            if (vis[v] > tm0) {
              continue;
            }
            if (check(u, v)) {
              if (v == goal) {
                return tm;
              }
              vis[v] = tm;
              q.push(v);
            }
          }
        }
      }
    }
  }
}
int main() {
  int w, h;
  while (scanf("%d%d%*d ", &w, &h), w) {
    for (int i = 0; i < h; ++i) {
      fgets(c[i], 20, stdin);
    }
    int goal = 0;
    int start = 0;
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        if (c[i][j] == '#') {
          wall[i << 4 | j] = true;
        } else {
          wall[i << 4 | j] = false;
          if (isupper(c[i][j])) {
            goal |= (i << 4 | j) << (c[i][j] - 'A') * 8;
          } else if (islower(c[i][j])) {
            start |= (i << 4 | j) << (c[i][j] - 'a') * 8;
          }
        }
      }
    }
    int tm = solve(start, goal);
    printf("%d\n", tm - tm0);
    tm0 = (tm0 + tm + 1) % 60000;   // Avoid resetting the vis array
  }
}
accuracy: 1
time_ms: 4690
memory_kb: 25420
final_rank: 8

code_snippet: #include <cctype>
#include <cstdio>
#include <cstring>
#include <deque>
using namespace std;
unsigned short vis[1 << 24];
char c[16][20];
bool wall[256];
int tm0;
inline bool check(int u, int v) {
  for (int i = 0; i < 24; i += 8) {
    int p1 = v >> i & 255;
    if (p1) {
      int j = i == 16 ? 0 : i + 8;
      if (wall[p1]) {
        return false;
      }
      int p2 = (v >> j % 24) & 255;
      if (p1 == p2) {
        return false;
      }
      if (p1 == (u >> j % 24 & 255) && p2 == (u >> i % 24 & 255)) {
        return false;
      }
    }
  }
  return true;
}
int solve(int start, int goal) {
  const int dif[5] = {0, -1, 1, -16, 16};
  deque<int> q;
  q.push_back(start);
  q.push_back(-1);
  int tm = tm0 + 1;
  vis[start] = tm;
  while (1) {
    int u = q.front();
    q.pop_front();
    if (u < 0) {
      q.push_back(-1);
      ++tm;
    } else {
      int u8 = u >> 8 & 255;
      int u16 = u >> 16;
      for (int i1 = u & 255 ? 4 : 0; i1 >= 0; --i1)
        for (int i2 = u8 ? 4 : 0; i2 >= 0; --i2)
          for (int i3 = u16 ? 4 : 0; i3 >= 0; --i3) {
            int v = u + dif[i1] + (dif[i2] << 8) + (dif[i3] << 16);
            if (vis[v] > tm0) {
              continue;
            }
            if (check(u, v)) {
              if (v == goal) {
                return tm;
              }
              vis[v] = tm;
              q.push_back(v);
            }
          }
    }
  }
}
int main() {
  int w, h;
  while (scanf("%d%d%*d ", &w, &h), w) {
    for (int i = 0; i < h; ++i) {
      fgets(c[i], 20, stdin);
    }
    int goal = 0;
    int start = 0;
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        if (c[i][j] == '#') {
          wall[i << 4 | j] = true;
        } else {
          wall[i << 4 | j] = false;
          if (isupper(c[i][j])) {
            goal |= (i << 4 | j) << (c[i][j] - 'A') * 8;
          } else if (islower(c[i][j])) {
            start |= (i << 4 | j) << (c[i][j] - 'a') * 8;
          }
        }
      }
    }
    int tm = solve(start, goal);
    printf("%d\n", tm - tm0);
    tm0 = tm + 1;
    if (tm0 > 55000) {
      memset(vis, 0, sizeof vis);
      tm0 = 0;
    }
  }
}
accuracy: 1
time_ms: 4710
memory_kb: 25408
final_rank: 10

code_snippet: #include <cctype>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
unsigned short vis[1 << 24];
char c[16][20];
bool wall[256];
int tm0;
inline bool check(int u, int v) {
  for (int i = 0; i < 24; i += 8) {
    int p1 = v >> i & 255;
    if (p1) {
      int j = i == 16 ? 0 : i + 8;
      if (wall[p1]) {
        return false;
      }
      int p2 = (v >> j) & 255;
      if (p1 == p2) {
        return false;
      }
      if (p1 == (u >> j & 255) && p2 == (u >> i & 255)) {
        return false;
      }
    }
  }
  return true;
}
inline int solve(int start, int goal) {
  const int dif[5] = {0, -1, 1, -16, 16};
  queue<int> q;
  q.push(start);
  q.push(-1);
  int tm = tm0 + 1;
  vis[start] = tm;
  while (1) {
    int u = q.front();
    q.pop();
    if (u < 0) {
      q.push(-1);
      ++tm;
    } else {
      for (int i1 = u & 255 ? 4 : 0; i1 >= 0; --i1)
        for (int i2 = u >> 8 & 255 ? 4 : 0; i2 >= 0; --i2)
          for (int i3 = u >> 16 ? 4 : 0; i3 >= 0; --i3) {
            int v = u + dif[i1] + (dif[i2] << 8) + (dif[i3] << 16);
            if (vis[v] > tm0) {
              continue;
            }
            if (check(u, v)) {
              if (v == goal) {
                return tm;
              }
              vis[v] = tm;
              q.push(v);
            }
          }
    }
  }
}
int main() {
  int w, h;
  while (scanf("%d%d%*d ", &w, &h), w) {
    for (int i = 0; i < h; ++i) {
      fgets(c[i], 20, stdin);
    }
    int goal = 0;
    int start = 0;
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        if (c[i][j] == '#') {
          wall[i << 4 | j] = true;
        } else {
          wall[i << 4 | j] = false;
          if (isupper(c[i][j])) {
            goal |= (i << 4 | j) << (c[i][j] - 'A') * 8;
          } else if (islower(c[i][j])) {
            start |= (i << 4 | j) << (c[i][j] - 'a') * 8;
          }
        }
      }
    }
    int tm = solve(start, goal);
    printf("%d\n", tm - tm0);
    tm0 = tm + 1;
    if (tm0 > 55000) {
      memset(vis, 0, sizeof vis);
      tm0 = 0;
    }
  }
}
accuracy: 1
time_ms: 4540
memory_kb: 25432
final_rank: 7

code_snippet: #include <cctype>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
unsigned short vis[1 << 24];
char c[16][20];
bool wall[256];
int tm0;
inline bool check(int u, int v) {
  for (int i = 0; i < 24; i += 8) {
    int p1 = v >> i & 255;
    if (p1) {
      int j = i == 16 ? 0 : i + 8;
      if (wall[p1]) {
        return false;
      }
      int p2 = (v >> (j & 24)) & 255;
      if (p1 == p2) {
        return false;
      }
      if (p1 == (u >> (j & 24) & 255) && p2 == (u >> (i & 24) & 255)) {
        return false;
      }
    }
  }
  return true;
}
int solve(int start, int goal) {
  const int dif[5] = {0, -1, 1, -16, 16};
  queue<int> q;
  q.push(start);
  q.push(-1);
  int tm = tm0 + 1;
  vis[start] = tm;
  while (1) {
    int u = q.front();
    q.pop();
    if (u < 0) {
      q.push(-1);
      ++tm;
    } else {
      for (int i1 = u & 255 ? 4 : 0; i1 >= 0; --i1)
        for (int i2 = u >> 8 & 255 ? 4 : 0; i2 >= 0; --i2)
          for (int i3 = u >> 16 ? 4 : 0; i3 >= 0; --i3) {
            int v = u + dif[i1] + (dif[i2] << 8) + (dif[i3] << 16);
            if (vis[v] > tm0) {
              continue;
            }
            if (check(u, v)) {
              if (v == goal) {
                return tm;
              }
              vis[v] = tm;
              q.push(v);
            }
          }
    }
  }
}
int main() {
  int w, h;
  while (scanf("%d%d%*d ", &w, &h), w) {
    for (int i = 0; i < h; ++i) {
      fgets(c[i], 20, stdin);
    }
    int goal = 0;
    int start = 0;
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        char current = c[i][j];
        bool isUpper = isupper(current);
        bool isLower = islower(current);
        if (current == '#') {
          wall[i << 4 | j] = true;
        } else {
          wall[i << 4 | j] = false;
          if (isUpper) {
            goal |= (i << 4 | j) << (current - 'A') * 8;
          } else if (isLower) {
            start |= (i << 4 | j) << (current - 'a') * 8;
          }
        }
      }
    }
    int tm = solve(start, goal);
    printf("%d\n", tm - tm0);
    tm0 = tm + 1;
    if (tm0 > 55000) {
      memset(vis, 0, sizeof vis);
      tm0 = 0;
    }
  }
}
accuracy: 1
time_ms: 4440
memory_kb: 25344
final_rank: 3

code_snippet: #include <cctype>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
unsigned short vis[1 << 24];
char c[16][20];
bool wall[256];
int tm0;
inline bool check(int u, int v) {
  for (int i = 0; i < 24; i += 8) {
    int p1 = v >> i & 255;
    if (p1) {
      int j = i == 16 ? 0 : i + 8;
      if (wall[p1]) {
        return false;
      }
      int p2 = (v >> (j == 24 ? 0 : j)) & 255;
      if (p1 == p2) {
        return false;
      }
      if (p1 == (u >> (j == 24 ? 0 : j) & 255) && p2 == (u >> i & 255)) {
        return false;
      }
    }
  }
  return true;
}
int solve(int start, int goal) {
  const int dif[5] = {0, -1, 1, -16, 16};
  queue<int> q;
  q.push(start);
  q.push(-1);
  int tm = tm0 + 1;
  vis[start] = tm;
  while (1) {
    int u = q.front();
    q.pop();
    if (u < 0) {
      q.push(-1);
      ++tm;
    } else {
      for (int i1 = u & 255 ? 4 : 0; i1 >= 0; --i1)
        for (int i2 = u >> 8 & 255 ? 4 : 0; i2 >= 0; --i2)
          for (int i3 = u >> 16 ? 4 : 0; i3 >= 0; --i3) {
            int v = u + dif[i1] + (dif[i2] << 8) + (dif[i3] << 16);
            if (vis[v] > tm0) {
              continue;
            }
            if (check(u, v)) {
              if (v == goal) {
                return tm;
              }
              vis[v] = tm;
              q.push(v);
            }
          }
    }
  }
}
int main() {
  int w, h;
  while (scanf("%d%d%*d ", &w, &h), w) {
    for (int i = 0; i < h; ++i) {
      fgets(c[i], 20, stdin);
    }
    int goal = 0;
    int start = 0;
    memset(wall, false, sizeof(wall));
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        if (c[i][j] == '#') {
          wall[i << 4 | j] = true;
        } else {
          if (isupper(c[i][j])) {
            goal |= (i << 4 | j) << ((c[i][j] - 'A') << 3);
          } else if (islower(c[i][j])) {
            start |= (i << 4 | j) << ((c[i][j] - 'a') << 3);
          }
        }
      }
    }
    int tm = solve(start, goal);
    printf("%d\n", tm - tm0);
    tm0 = tm + 1;
    if (tm0 > 55000) {
      memset(vis, 0, sizeof vis);
      tm0 = 0;
    }
  }
}
accuracy: 1
time_ms: 4480
memory_kb: 25328
final_rank: 5

code_snippet: #include <cctype>
#include <cstdio>
#include <cstring>
#include <queue>

unsigned short vis[1 << 24];
char c[16][20];
bool wall[256];
int tm0;

inline bool check(int u, int v) {
  for (int i = 0; i < 24; i += 8) {
    int p1 = v >> i & 255;
    if (p1) {
      int j = i == 16 ? 0 : i + 8;
      if (wall[p1]) {
        return false;
      }
      int p2 = (v >> j % 24) & 255;
      if (p1 == p2) {
        return false;
      }
      if (p1 == (u >> j % 24 & 255) && p2 == (u >> i % 24 & 255)) {
        return false;
      }
    }
  }
  return true;
}

int solve(int start, int goal) {
  const int dif[5] = {0, -1, 1, -16, 16};
  std::queue<int> q;
  q.push(start);
  q.push(-1);
  int tm = tm0 + 1;
  vis[start] = tm;
  while (1) {
    int u = q.front();
    q.pop();
    if (u < 0) {
      q.push(-1);
      ++tm;
    } else {
      for (int i1 = u & 255 ? 4 : 0; i1 >= 0; --i1)
        for (int i2 = u >> 8 & 255 ? 4 : 0; i2 >= 0; --i2)
          for (int i3 = u >> 16 ? 4 : 0; i3 >= 0; --i3) {
            int v = u + dif[i1] + (dif[i2] << 8) + (dif[i3] << 16);
            if (check(u, v) && vis[v] <= tm0) {
              if (v == goal) {
                return tm;
              }
              vis[v] = tm;
              q.push(v);
            }
          }
    }
  }
}

int main() {
  int w, h;
  while (scanf("%d%d%*d ", &w, &h), w) {
    for (int i = 0; i < h; ++i) {
      fgets(c[i], 20, stdin);
    }
    int goal = 0;
    int start = 0;
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        int ij = i << 4 | j;
        if (c[i][j] == '#') {
          wall[ij] = true;
        } else {
          wall[ij] = false;
          if (isupper(c[i][j])) {
            goal |= ij << (c[i][j] - 'A') * 8;
          } else if (islower(c[i][j])) {
            start |= ij << (c[i][j] - 'a') * 8;
          }
        }
      }
    }
    int tm = solve(start, goal);
    printf("%d\n", tm - tm0);
    tm0 = tm + 1;
    if (tm0 > 55000) {
      memset(vis, 0, sizeof vis);
      tm0 = 0;
    }
  }
}
accuracy: 1
time_ms: 4700
memory_kb: 25476
final_rank: 9

code_snippet: // UVa1601 The Morning after Halloween
#include <bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (int)(b); ++i)
typedef long long LL;
using VI = vector<int>;
const int MAXV = 16 * 16 + 4;
const VI DX{-1, 1, 0, 0, 0}, DY{0, 0, -1, 1, 0};
VI X(MAXV), Y(MAXV), Src(3), Dest(3);
vector<VI> ID(16, VI(16)), G(MAXV);
// 3个人的位置编码
inline int enc(int a, int b, int c) { return (a << 16) + (b << 8) + c; }
// (a,b)->(na,nb)冲突吗?
inline bool conflict(int a, int b, int na, int nb) {
  assert(a != b);
  return (na == nb || (na == b && nb == a));  // 相等或者只是交换了位置
}
int bfs() {  // 三个人同时走
  queue<int> Q;
  unordered_map<int, int> D;
  int st = enc(Src[0], Src[1], Src[2]);  // 从起点开始bfs
  Q.push(st), D[st] = 0;
  while (!Q.empty()) {  // 从x中解码出3个人的位置
    int x = Q.front(), a = x >> 16, b = (x >> 8) & 255, c = x & 255, d = D[x];
    Q.pop();
    if (a == Dest[0] && b == Dest[1] && c == Dest[2]) return d;  // 到达目的地了
    for (int na : G[a])                        // a的下一个位置
      for (int nb : G[b]) {                    // b的下一个位置
        if (conflict(a, b, na, nb)) continue;  // a,b冲突
        for (int nc : G[c]) {
          int ne = enc(na, nb, nc);  // 3个人的新位置编码
          if (!conflict(a, c, na, nc) && !conflict(b, c, nb, nc) &&
              !D.count(ne))             // a,c和b,c不冲突,且没有访问过
            D[ne] = d + 1, Q.push(ne);  // 记录路径,入队
        }
      }
  }
  return -1;
}
int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  for (int W, H, N, V; cin >> W >> H >> N && W;) {
    cin.ignore(), V = 0;
    vector<string> MAP(H);
    _for(r, 0, H) {
      getline(cin, MAP[r]);
      _for(c, 0, W) {
        char ch = MAP[r][c];
        if (ch == '#') continue;
        ID[r][c] = V, X[V] = r, Y[V] = c;     // 每个点一个编号
        if (isupper(ch)) Dest[ch - 'A'] = V;  // 目的地的编号
        if (islower(ch)) Src[ch - 'a'] = V;   // 起点的编号
        ++V;
      }
    }
    _for(u, 0, V) {
      G[u].clear();
      int x = X[u], y = Y[u];
      _for(d, 0, 5) {  // 考虑(x,y)的5个方向可达的点
        int nx = x + DX[d], ny = y + DY[d];
        if (0 <= nx && nx < H && 0 <= ny && ny < W && MAP[nx][ny] != '#')
          G[u].push_back(ID[nx][ny]);  // 建图
      }
    }
    if (N <= 2) Src[2] = Dest[2] = V, G[V].clear(), G[V].push_back(V), ++V;
    if (N <= 1) Src[1] = Dest[1] = V, G[V].clear(), G[V].push_back(V), ++V;
    printf("%d\n", bfs());
  }
  return 0;
}
// 19354384 1601  The Morning after Halloween Accepted  C++11 1.010 2017-05-12
// 00:02:59
accuracy: 1
time_ms: 5180
memory_kb: 59444
final_rank: 20

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

struct ghost {
	int start, goal;
};

int solve(int N, int K, const vector<vector<int> >& G, const vector<ghost>& H) {
	// step #1. calculate distances
	vector<vector<int> > d(N, vector<int>(N, -1));
	for (int i = 0; i < N; i++) {
		vector<int> st = { i };
		d[i][i] = 0;
		while (!st.empty()) {
			int u = st.back();
			st.pop_back();
			for (int j : G[u]) {
				if (d[i][j] == -1) {
					d[i][j] = d[i][u] + 1;
					st.push_back(j);
				}
			}
		}
	}
	vector<vector<int> > dsub(K);
	for (int i = 0; i < K; i++) {
		dsub[i] = d[H[i].goal];
	}
	
	// step #2. preparation
	vector<int> power(K + 1);
	power[0] = 1;
	for (int i = 1; i <= K; i++) {
		power[i] = power[i - 1] * N;
	}
	int start = 0;
	int goal = 0;
	for (int i = 0; i < K; i++) {
		start += H[i].start * power[i];
		goal += H[i].goal * power[i];
	}

	// step #3. bfs
	vector<int> dist(power[K], -1);
	queue<int> que;
	dist[start] = 0;
	que.push(start);
	while (!que.empty()) {
		int cid = que.front();
		que.pop();
		vector<int> cs(K);
		for (int i = 0; i < K; i++) {
			cs[i] = (cid / power[i]) % N;
		}
		vector<bool> flag(K, false);
		for (int i = 0; i < K; i++) {
			for (int j = i + 1; j < K; j++) {
				if (d[cs[i]][cs[j]] <= 2) {
					flag[i] = true;
					flag[j] = true;
				}
			}
		}
		vector<int> ns(K);
		auto dfs = [&](auto& self, int depth, int nid) -> void {
			if (depth == K) {
				bool valid = true;
				for (int i = 0; i < K; i++) {
					for (int j = i + 1; j < K; j++) {
						if (ns[i] == ns[j]) {
							valid = false;
						}
						if (ns[i] == cs[j] && ns[j] == cs[i]) {
							valid = false;
						}
					}
				}
				if (valid && dist[nid] == -1) {
					dist[nid] = dist[cid] + 1;
					que.push(nid);
				}
				return;
			}
			for (int i : G[cs[depth]]) {
				if (flag[depth] || dsub[depth][i] == max(dsub[depth][cs[depth]] - 1, 0)) {
					ns[depth] = i;
					self(self, depth + 1, nid + i * power[depth]);
				}
			}
			if (flag[depth] || dsub[depth][cs[depth]] == 0) {
				ns[depth] = cs[depth];
				self(self, depth + 1, nid + cs[depth] * power[depth]);
			}
		};
		dfs(dfs, 0, 0);
	}

	return dist[goal];
}

int main() {
	while (true) {
		int H, W, N;
		cin >> W >> H >> N; cin.ignore();
		if (H == 0 && W == 0 && N == 0) {
			break;
		}
		vector<string> S(H);
		for (int i = 0; i < H; i++) {
			getline(cin, S[i]);
		}
		int vcnt = 0;
		vector<ghost> I(N);
		vector<vector<int> > v(H, vector<int>(W, -1));
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) {
				if (S[i][j] != '#') {
					v[i][j] = vcnt;
					vcnt += 1;
				}
				if ('a' <= S[i][j] && S[i][j] <= 'z') {
					I[S[i][j] - 'a'].start = v[i][j];
				}
				if ('A' <= S[i][j] && S[i][j] <= 'Z') {
					I[S[i][j] - 'A'].goal = v[i][j];
				}
			}
		}
		const vector<int> dx = { 1, 0, -1, 0 };
		const vector<int> dy = { 0, 1, 0, -1 };
		auto access = [&](int x, int y) -> int {
			return (0 <= x && x < H && 0 <= y && y < W ? v[x][y] : -1);
		};
		vector<vector<int> > G(vcnt);
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) {
				if (v[i][j] != -1) {
					for (int k = 0; k < 4; k++) {
						int id = access(i + dx[k], j + dy[k]);
						if (id != -1) {
							G[v[i][j]].push_back(id);
						}
					}
				}
			}
		}
		int ans = solve(vcnt, N, G, I);
		cout << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 13840
final_rank: 1

code_snippet: #include <cctype>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
unsigned short vis[1 << 24];
char c[16][20];
bool wall[256];
int tm0;
inline bool check(int u, int v) {
  for (int i = 0; i < 24; i += 8) {
    int p1 = v >> i & 255;
    if (p1) {
      int j = i == 16 ? 0 : i + 8;
      if (wall[p1]) {
        return false;
      }
      int p2 = (v >> j) & 255;
      if (p1 == p2) {
        return false;
      }
      if (p1 == (u >> j & 255) && p2 == (u >> i & 255)) {
        return false;
      }
    }
  }
  return true;
}
int solve(int start, int goal) {
  const int dif[5] = {0, -1, 1, -16, 16};
  queue<int> q;
  q.push(start);
  q.push(-1);
  int tm = tm0 + 1;
  vis[start] = tm;
  while (1) {
    int u = q.front();
    q.pop();
    if (u < 0) {
      q.push(-1);
      ++tm;
    } else {
      for (int i1 = u & 255 ? 4 : 0; i1 >= 0; --i1)
        for (int i2 = u >> 8 & 255 ? 4 : 0; i2 >= 0; --i2)
          for (int i3 = u >> 16 ? 4 : 0; i3 >= 0; --i3) {
            int v = u + dif[i1] + (dif[i2] << 8) + (dif[i3] << 16);
            if (vis[v] > tm0) {
              continue;
            }
            if (check(u, v)) {
              if (v == goal) {
                return tm;
              }
              vis[v] = tm;
              q.push(v);
            }
          }
    }
  }
}
int main() {
  int w, h;
  while (scanf("%d%d%*d ", &w, &h), w) {
    for (int i = 0; i < h; ++i) {
      fgets(c[i], 20, stdin);
    }
    int goal = 0;
    int start = 0;
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        if (c[i][j] == '#') {
          wall[i << 4 | j] = true;
        } else {
          wall[i << 4 | j] = false;
          if (isupper(c[i][j])) {
            goal |= (i << 4 | j) << ((c[i][j] - 'A') << 3);
          } else if (islower(c[i][j])) {
            start |= (i << 4 | j) << ((c[i][j] - 'a') << 3);
          }
        }
      }
    }
    int tm = solve(start, goal);
    printf("%d\n", tm - tm0);
    tm0 = tm + 1;
    if (tm0 > 55000) {
      memset(vis, 0, sizeof vis);
      tm0 = 0;
    }
  }
}
accuracy: 1
time_ms: 4470
memory_kb: 25500
final_rank: 6

code_snippet: #include <cctype>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

unsigned short vis[1 << 24];
char c[16][20];
bool wall[256];
int tm0;

inline bool check(int u, int v) {
  for (int i = 0; i < 24; i += 8) {
    int p1 = v >> i & 255;
    if (p1) {
      if (wall[p1]) {
        return false;
      }
      int p2 = (v >> ((i + 8) % 24)) & 255;
      if ((p1 == p2) || (p1 == (u >> ((i + 8) % 24) & 255) && p2 == (u >> i % 24 & 255)))
        return false;
    }
  }
  return true;
}

int solve(int start, int goal) {
  const int dif[5] = {0, -1, 1, -16, 16};
  queue<int> q;
  q.push(start);
  q.push(-1);
  int tm = tm0 + 1;
  vis[start] = tm;
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    if (u < 0) {
      if (q.empty())
        break;
      q.push(-1);
      ++tm;
    } else {
      for (int i1 = (u & 255) ? 4 : 0; i1 >= 0; --i1)
        for (int i2 = (u >> 8 & 255) ? 4 : 0; i2 >= 0; --i2)
          for (int i3 = u >> 16 ? 4 : 0; i3 >= 0; --i3) {
            int v = u + dif[i1] + (dif[i2] << 8) + (dif[i3] << 16);
            if (vis[v] > tm0 || !check(u, v)) {
              continue;
            }
            if (v == goal) {
              return tm;
            }
            vis[v] = tm;
            q.push(v);
          }
    }
  }
  return -1;
}

int main() {
  int w, h;
  while (scanf("%d%d%*d ", &w, &h), w) {
    for (int i = 0; i < h; ++i) {
      fgets(c[i], 20, stdin);
    }
    int goal = 0, start = 0;
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        int ij = i << 4 | j;
        wall[ij] = c[i][j] == '#';
        if (!wall[ij]) {
          if (isupper(c[i][j])) {
            goal |= ij << (c[i][j] - 'A') * 8;
          } else if (islower(c[i][j])) {
            start |= ij << (c[i][j] - 'a') * 8;
          }
        }
      }
    }
    int tm = solve(start, goal);
    printf("%d\n", tm - tm0);
    tm0 = tm + 1;
    if (tm0 > 55000) {
      memset(vis, 0, sizeof vis);
      tm0 = 0;
    }
  }
}
accuracy: 1
time_ms: 4950
memory_kb: 25500
final_rank: 11