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
- 공간 복잡도
- 요세푸스 문제
- BFS
- 배열
- toLowerCase()
- 너비 우선 탐색
- MySQL
- IS NOT NULL
- 문자열
- 연결 리스트
- 거듭제곱
- 정렬
- 그래프 이론
- 그리디 알고리즘
- ListIterator
- 브루트포스
- toUpperCase()
- 스택
- 구현
- 정수론
- 수학
- ifnull
- 소수 판정
- 백트래킹
- 빅오 표기법
- 자료 구조
- 큐
- 그래프 탐색
- 분할 정복
- 시간 복잡도
Archives
- Today
- Total
배푸니까
[백준 / JAVA] 4179. 불! 본문
반응형
https://www.acmicpc.net/problem/4179
4179번: 불!
입력의 첫째 줄에는 공백으로 구분된 두 정수 R과 C가 주어진다. 단, 1 ≤ R, C ≤ 1000 이다. R은 미로 행의 개수, C는 열의 개수이다. 다음 입력으로 R줄동안 각각의 미로 행이 주어진다. 각각의 문자
www.acmicpc.net
💻 풀이 결과
💯 최종 코드
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
class Node {
int r, c;
Node(int r, int c) {
this.r = r;
this.c = c;
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int R = sc.nextInt();
int C = sc.nextInt();
char[][] map = new char[R][C];
Queue<Node> fire = new LinkedList<>();
Queue<Node> jihoon = new LinkedList<>();
boolean[][] visited = new boolean[R][C];
for (int i = 0; i < R; i++) {
String str = sc.next();
for (int j = 0; j < C; j++) {
map[i][j] = str.charAt(j);
if (map[i][j] == 'F') {
fire.add(new Node(i, j));
}
if (map[i][j] == 'J') {
jihoon.add(new Node(i, j));
visited[i][j] = true;
}
}
}
int cnt = 0;
int[] dr = { 0, 0, -1, 1 };
int[] dc = { -1, 1, 0, 0 };
boolean isPossible = false;
// 지훈이가 가장자리로 갈 때까지
while (!jihoon.isEmpty()) {
// 매분마다 불이 확산된다.
int fireSize = fire.size();
for (int fs = 0; fs < fireSize; fs++) {
Node curr = fire.poll();
for (int d = 0; d < 4; d++) {
int nr = curr.r + dr[d];
int nc = curr.c + dc[d];
if (nr < 0 || nc < 0 || nr >= R || nc >= C) {
continue;
}
// 불이 퍼진 지점을 큐에 삽입
if (map[nr][nc] == '.') {
fire.add(new Node(nr, nc));
// 불 났다고 표시
map[nr][nc] = 'F';
}
}
} // 불 퍼지는 것 끝
int size = jihoon.size();
cnt++;
for (int s = 0; s < size; s++) {
Node curr = jihoon.poll();
// 종료 조건
if (curr.r == 0 || curr.r == R - 1 || curr.c == 0 || curr.c == C - 1) {
isPossible = true;
jihoon.clear();
break;
}
for (int d = 0; d < 4; d++) {
int nr = curr.r + dr[d];
int nc = curr.c + dc[d];
if (nr < 0 || nc < 0 || nr >= R || nc >= C) {
continue;
}
if (visited[nr][nc]) {
continue;
}
// 이동할 수 있는 지점을 큐에 삽입
if (map[nr][nc] == '.') {
jihoon.add(new Node(nr, nc));
visited[nr][nc] = true;
map[curr.r][curr.c] = '.';
}
}
}
}
if (isPossible) {
System.out.println(cnt);
} else {
System.out.println("IMPOSSIBLE");
}
}
}
💢 틀린 이유
1. 메모리 초과
- 지훈이의 위치 노드를 담는 큐에서 메모리 초과가 발생한 것을 발견하였다.
- 메모리 초과가 발생한 이유는 지훈이 위치를 큐에 담을 때 방문처리를 하지 않아서 계속해서 다음 갈 수 있는 위치들이 큐에 담기는 로직이었기 때문이다.
- visited 배열을 만들어 지훈이 위치에 대해 방문 처리를 해줘서 해결하였다.
2. 불의 확산 vs 지훈이의 이동
- 처음 구현한 로직은 불의 확산과 지훈이의 이동의 순서를 고려하지 않았다.
- 생각해 보니 사건은 동시에 일어나기 때문에, 불을 먼저 확산시키고 불이 퍼진 자리는 지훈이가 이동하지 못하도록 처리하였다.
💬 풀이 과정
- BFS 큰 틀은 지훈이 위치에 대한 큐가 비었을 때 종료하도록 하였다.
- 불이 난 자리들의 위치와 지훈이의 위치를 각각 큐에 삽입한 채로 시작하였다.
- 1초 단위로 일어나는 일들을 순서대로 구현한다는 생각으로, 불들을 확산시키고 지훈이를 이동시켰다.
- 4방 탐색을 통해 불을 확산시키고 불이 퍼진 자리를 처리하였다.
- 불이 한번 퍼질 때마다 지훈이를 한번 이동시키고 방문처리하였다.
- 지훈이 위치를 꺼냈을 때 탈출할 수 있는 지점이라면 큐를 비워 즉시 종료되도록 하였다.
💡 깨달은 점
1. BFS 응용 - 시작점이 두 종류일 때
- 두 시작점에 대한 각각의 BFS를 돌린다.
- 두 BFS에 대한 처리 순서를 신경 써야 한다.
- 두 BFS가 서로 영향을 주는 문제의 경우에는 이러한 로직으로 풀 수가 없다. 그래서 시간 순으로 동시에 진행시켜야 한다. (백트래킹 기법 사용 필요)
반응형
'백준' 카테고리의 다른 글
[백준 / JAVA] 1012. 유기농 배추 (0) | 2023.08.06 |
---|---|
[백준 / JAVA] 1697. 숨바꼭질 (0) | 2023.08.02 |
[백준 / JAVA] 7576. 토마토 (0) | 2023.08.02 |
[백준 / JAVA] 2178. 미로 탐색 (1) | 2023.08.02 |
[백준 / JAVA] 24445. 알고리즘 수업 - 너비 우선 탐색 2 (0) | 2023.08.01 |