Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 개발자취업
- 플로이드-워셜
- Java
- 데이터베이스
- 99클럽
- 자바스크립트
- 파이썬
- 1일1코테
- 웹
- #코드트리 #코딩테스트 #코테공부 #백트래킹 #알고리즘 기초
- C
- 코딩테스트
- 코딩테스트준비
- 티스토리챌린지
- 항해99
- 운영체제
- 코드트리
- 갭체크
- 연결 리스트
- 개발자루틴
- 자료구조
- 자바
- 코딩테스트사이트추천
- 프로그래머스
- til
- 오블완
- 인접 행렬
- 프로그래밍 언어
- 코테공부
- 알고리즘
Archives
- Today
- Total
와드의 블로그
4179번: 불! 본문
문제
미로에서 지훈이가 불을 피해 탈출하려고 합니다. 미로의 가장자리에 도달하면 탈출에 성공한 것으로 간주합니다. 지훈이와 불은 매 분마다 상하좌우로 인접한 칸으로 이동(확산)하며, 불은 각 지점에서 네 방향으로 동시에 확산됩니다. 지훈이는 벽이 있는 칸이나 불이 번진 칸, 그리고 불이 번질 예정인 칸으로는 이동할 수 없습니다. 지훈이가 불을 피해 탈출할 수 있는 가장 빠른 시간을 구하는 문제입니다.
- 입력: 첫째 줄에 행의 개수 R과 열의 개수 C가 주어집니다. 다음 R개의 줄에 미로의 상태가 주어집니다. (#: 벽, .: 지나갈 수 있는 공간, J: 지훈이의 초기 위치, F: 불이 난 공간)
- 출력: 탈출할 수 있는 가장 빠른 시간을 출력합니다. 탈출할 수 없다면 "IMPOSSIBLE"을 출력합니다.
링크: https://www.acmicpc.net/problem/4179
풀이: 두 개의 BFS를 활용한 시간 비교
불의 확산 시간과 지훈이의 이동 시간을 각각 구하여 비교하는 전형적인 두 큐(Queue) 활용 BFS 문제입니다.
- 불(Fire)의 이동 시간 미리 구하기: 불은 지훈이의 이동 경로와 무관하게 정해진 대로 확산합니다. 따라서 불의 위치를 모두 큐(qF)에 넣고 먼저 BFS 탐색을 진행하여, 미로의 각 칸에 불이 도달하는 최소 시간(fire 배열)을 모두 계산해 둡니다. 불이 도달하지 않는 곳은 안전한 탐색을 위해 Integer.MAX_VALUE로 초기화합니다.
- 지훈이(J)의 탈출 경로 탐색: 지훈이의 시작 위치를 큐(qP)에 넣고 두 번째 BFS 탐색을 진행합니다.
- 탈출 조건: 큐에서 꺼낸 지훈이의 현재 위치가 미로의 가장자리(행이 0이거나 R-1, 열이 0이거나 C-1)라면 즉시 탈출에 성공한 것입니다. 방문 배열에 기록된 시간을 출력하고 프로그램을 종료합니다.
- 이동 조건: 지훈이가 다음 칸으로 이동하려면 다음 조건을 모두 만족해야 합니다.
- 맵의 범위를 벗어나지 않아야 합니다.
- 벽(#)이 아니어야 합니다.
- 불이 도달하는 시간(fire[ny][nx])이 지훈이가 도달할 시간(visited[node.y][node.x] + 1)보다 커야 합니다. (즉, 불보다 먼저 도착해야 함)
- 아직 방문하지 않은 칸(visited[ny][nx] == 0)이어야 합니다.
- 예외 처리: 지훈이의 BFS 탐색이 큐가 빌 때까지 끝났는데도 가장자리에 도달하지 못했다면, 탈출 경로가 불에 막히거나 벽에 갇힌 것이므로 "IMPOSSIBLE"을 출력합니다.
코드
import java.io.*;
import java.util.*;
public class Main {
// 상하좌우 이동을 위한 델타 배열
static int[] dy = {-1, 0, 1, 0};
static int[] dx = {0, 1, 0, -1};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
int r = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
Queue<Node> qP = new LinkedList<>(); // 지훈이의 이동 큐
int[][] visited = new int[r][c]; // 지훈이의 방문 시간 기록
Queue<Node> qF = new LinkedList<>(); // 불의 확산 큐
int[][] fire = new int[r][c]; // 불이 도달하는 시간 기록
char[][] a = new char[r][c];
for (int i = 0; i < r; i++) {
String s = br.readLine();
for (int j = 0; j < c; j++) {
a[i][j] = s.charAt(j);
// 불이 영원히 닿지 않는 곳을 위해 초기값을 무한대로 설정
fire[i][j] = Integer.MAX_VALUE;
if (a[i][j] == 'J') {
qP.add(new Node(i, j));
visited[i][j] = 1; // 시간 계산 편의를 위해 1부터 시작
} else if (a[i][j] == 'F') {
qF.add(new Node(i, j));
fire[i][j] = 1;
}
}
}
// 1. 불의 확산 시간을 먼저 모두 계산 (BFS)
while (!qF.isEmpty()) {
Node node = qF.poll();
for (int i = 0; i < 4; i++) {
int ny = node.y + dy[i];
int nx = node.x + dx[i];
if (ny < 0 || nx < 0 || ny >= r || nx >= c)
continue;
// 벽이거나 이미 불이 더 일찍 번진 곳이라면 무시
if (a[ny][nx] == '#' || fire[ny][nx] != Integer.MAX_VALUE)
continue;
qF.add(new Node(ny, nx));
fire[ny][nx] = fire[node.y][node.x] + 1;
}
}
// 2. 지훈이의 이동 경로 탐색 (BFS)
while (!qP.isEmpty()) {
Node node = qP.poll();
// 현재 위치가 미로의 가장자리라면 탈출 성공
if (node.y == 0 || node.x == 0 || node.y == r - 1 || node.x == c - 1) {
bw.write(visited[node.y][node.x] + "");
bw.flush();
return;
}
for (int i = 0; i < 4; i++) {
int ny = node.y + dy[i];
int nx = node.x + dx[i];
if (ny < 0 || nx < 0 || ny >= r || nx >= c)
continue;
// 벽이거나, 불이 번지는 시간과 같거나 빠르거나, 이미 방문한 곳이라면 무시
if (a[ny][nx] == '#' || fire[ny][nx] <= visited[node.y][node.x] + 1 || visited[ny][nx] != 0)
continue;
qP.add(new Node(ny, nx));
visited[ny][nx] = visited[node.y][node.x] + 1;
}
}
// 큐가 빌 때까지 가장자리에 도달하지 못했다면 탈출 실패
bw.write("IMPOSSIBLE");
bw.flush();
bw.close();
br.close();
}
static class Node {
int y, x;
Node(int y, int x) {
this.y = y;
this.x = x;
}
}
}
알고리즘 분류
그래프 탐색, 너비 우선 탐색 (BFS)
'PS > B.O.J' 카테고리의 다른 글
| 큰 수 A+B (2) (0) | 2026.03.29 |
|---|---|
| 12869번: 뮤탈리스크 (0) | 2026.03.28 |
| 16234번: 인구 이동 (0) | 2026.03.28 |
| 9934번: 완전 이진 트리 (0) | 2026.03.27 |
| 2529번: 부등호 (0) | 2026.03.27 |