[BOJ 6593] 상범빌딩

Lil_Young·2025년 6월 23일

알고리즘 문제

목록 보기
1/23
post-thumbnail

[문제]


시작지점(S)에서 도착지점(E) 까지 가는데, 걸리는 최소거리를 구하는 문제다.
도착이 가능하면,
Escaped in X minute(s).
도착이 불가능하면,
Trapped!
로 출력하면된다.

[풀이 코드]


import java.util.*;
import java.io.*;

public class 상범빌딩 {
	static int L, R, C;
	static char[][][] arr;
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		while(true) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			L = Integer.parseInt(st.nextToken());
			R = Integer.parseInt(st.nextToken());
			C = Integer.parseInt(st.nextToken());
			if(L==0 && R==0 && C==0) break;
			arr = new char[L][R][C];
			// start 위치
			int[] startIdx = new int[3];
			for (int t = 0; t < L; t++) {
				for (int i = 0; i < R; i++) {
					String s = br.readLine();
					for (int j = 0; j < C; j++) {
						arr[t][i][j] = s.charAt(j);
						if(arr[t][i][j]=='S') {
							startIdx[0] = t;
							startIdx[1] = i;
							startIdx[2] = j;
						}
					}
				}
				br.readLine();
			}			
			int result = bfs(startIdx[0], startIdx[1], startIdx[2]);
			if(result == -1) {
				System.out.println("Trapped!");
			}else {
				System.out.println("Escaped in " + result + " minute(s).");
			}
		}
	}
	static class Point {
		int t, r, c, cnt;
		Point(int t, int r, int c, int cnt){
			this.t=t;
			this.r=r;
			this.c=c;
			this.cnt=cnt;
		}
	}
	static int[] dr = {0, 0, 1, -1};
	static int[] dc = {1, -1, 0, 0};
	private static int bfs(int t, int r, int c) {
		Queue<Point> queue = new ArrayDeque<>();
		queue.offer(new Point(t, r, c, 0));
		boolean[][][] v = new boolean[L][R][C];
		v[t][r][c] = true;
		
		while(!queue.isEmpty()) {
			Point p = queue.poll();

			if(arr[p.t][p.r][p.c]=='E') {
				return p.cnt;
			}
			
			
			// 상하좌우
			for (int d = 0; d < 4; d++) {
				int nr = p.r + dr[d];
				int nc = p.c + dc[d];
				
				if(nr<0 || nr>=R || nc<0 || nc>=C || arr[p.t][nr][nc]=='#' || v[p.t][nr][nc]) continue;
				
				queue.offer(new Point(p.t, nr, nc, p.cnt+1));
				v[p.t][nr][nc] = true;
			}
			
			// 층 이동
			if(p.t+1<L && (arr[p.t+1][p.r][p.c]=='.' || arr[p.t+1][p.r][p.c]=='E') && !v[p.t+1][p.r][p.c]) {
				queue.offer(new Point(p.t+1, p.r, p.c, p.cnt+1));
				v[p.t+1][p.r][p.c] = true;
			}
			if(p.t-1>=0 && (arr[p.t-1][p.r][p.c]=='.' || arr[p.t-1][p.r][p.c]=='E') && !v[p.t-1][p.r][p.c]) {
				queue.offer(new Point(p.t-1, p.r, p.c, p.cnt+1));
				v[p.t-1][p.r][p.c] = true;
			}
			
		}
		
		return -1;
	}
}

필자는 문제를 자세하게 읽지 않아서, 문제를 풀 때 다음과 같은 실수를 했다.
1. 0 0 0 이 입력이 되기 전에는 무한루프로 입력을 받아야 하는데, 실행하면 한번만 입력받게 코드를 작성했다.
2. 층 이동을 할 때, 다음과 같이 범위 안에 있는 층일 경우 게속해서 Queue에 추가를 했다.

			// 층 이동
			for(int i=p.t+1; i<L; i++) {
				if(arr[i][p.r][p.c]=='.' || arr[i][p.r][p.c]=='E' && !v[i][p.r][p.c]) {
					queue.offer(new Point(i, p.r, p.c, p.cnt+1));
					v[i][p.r][p.c] = true;
				}
			}
			for(int i=p.t-1; i>=0; i--) {
				if((arr[i][p.r][p.c]=='.' || arr[i][p.r][p.c]=='E') && !v[i][p.r][p.c]) {
					queue.offer(new Point(i, p.r, p.c, p.cnt+1));
					v[i][p.r][p.c] = true;
				}
			}	

필자가 작성한 코드에서 개선할 수 있는 코드가 있는지 다른 사람이 작성한 코드를 확인해봤는데, 이동하는 배열을 4방탐색에서 6방탐색으로 다음과 같이 변경하면 코드 유지보수와 가독성도 좋아지는 것을 확인했다.

	static 	int[] dt = {0, 0, 0, 0, 1, -1};
	static int[] dr = {0, 0, 1, -1, 0, 0};
	static int[] dc = {1, -1, 0, 0, 0, 0};
	private static int bfs(int t, int r, int c) {
		Queue<Point> queue = new ArrayDeque<>();
		queue.offer(new Point(t, r, c, 0));
		boolean[][][] v = new boolean[L][R][C];
		v[t][r][c] = true;
		
		while(!queue.isEmpty()) {
			Point p = queue.poll();
			if(arr[p.t][p.r][p.c]=='E') {
				return p.cnt;
			}
			
			
			// 상하좌우 및 층 이동
			for (int d = 0; d < 6; d++) {
				int nt = p.t + dt[d];
				int nr = p.r + dr[d];
				int nc = p.c + dc[d];
				
				if(nt <0 || nt >= L || nr<0 || nr>=R || nc<0 || nc>=C || arr[nt][nr][nc]=='#' || v[nt][nr][nc]) continue;
				
				queue.offer(new Point(nt, nr, nc, p.cnt+1));
				v[nt][nr][nc] = true;
			}			
		}
		
		return -1;
	}

문제를 꼼꼼히 읽어보는 습관을 들이고, 가독성과 유지보수를 생각하고 코드를 작성하자.

0개의 댓글