Maximum Winter-Contest 2011 G: Stacked Rotatable Mazes
問題概要
3次元の迷路の最短距離を求める問題。ただし下方向への移動はできず、上方向には特定のマスからしかいけない。また、上に登る前に上の層を任意に回転させることができる。
解法
定石通り幅優先するだけ。サンプルが珍しく親切。
char board[4][MAX][MAX][MAX]; int N, M; int dz[] = {1,0,0,0,0}; int dy[] = {0,1,-1,0,0}; int dx[] = {0,0,0,1,-1}; bool isIn(int z, int y, int x){ return 0<=z && z<M && 0<=y && y<N && 0<=x && x<N; } void init(){ for(int k=1; k<4; k++){ for(int i=0; i<M; i++){ for(int j=0; j<N; j++){ for(int jj=0; jj<N; jj++){ board[k][i][j][jj] = board[k-1][i][jj][N-1-j]; } } } } } struct position{ int k, z, y, x, d; }; int solve(){ init(); int sx,sy; for(int i=0; i<N; i++)for(int j=0; j<N; j++)if(board[0][0][i][j]=='S'){ sx = j; sy = i; } board[0][0][sy][sx] = '*'; queue<position> Q; Q.push((position){0,0,sy,sx,0}); while(!Q.empty()){ position tp = Q.front(); Q.pop(); for(int k=0; k<5; k++){ int nz = tp.z + dz[k], ny = tp.y + dy[k], nx = tp.x + dx[k]; if(!isIn(nz,ny,nx)) continue; if(!k){ if(board[tp.k][tp.z][tp.y][tp.x] == 'Z')for(int kk=0; kk<4; kk++){ if(board[(tp.k+kk)%4][nz][ny][nx] == 'G') return tp.d+1; if(board[(tp.k+kk)%4][nz][ny][nx] == '.'){ Q.push((position){(tp.k+kk)%4,nz,ny,nx,tp.d+1}); board[(tp.k+kk)%4][nz][ny][nx] = '*'; } } } else{ if(board[tp.k][nz][ny][nx] != '*' && board[tp.k][nz][ny][nx] != 'Z'){ if(board[tp.k][nz][ny][nx] == 'G') return tp.d+1; Q.push((position){tp.k,nz,ny,nx,tp.d+1}); board[tp.k][nz][ny][nx] = board[tp.k][nz][ny][nx]=='U'?'Z':'*'; } } } } return -1; } int main(){ while(scanf("%d%d ",&N,&M)){ if(!N && !M) break; for(int i=0; i<M; i++){ for(int j=0; j<N; j++){ scanf("%s ",board[0][i][j]); } } printf("%d\n",solve()); } return 0; }