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
- biginteger사용법
- 컴파일시스템
- national instruments
- 자바
- 티스토리챌린지
- 자바입력받기
- TypeScript
- 2차원배열정렬
- CSS 기초
- 오블완
- Node
- 블록체인강의
- 혁신의기술2:신뢰의미래 블록체인을 만나다
- 딥러닝
- 머신러닝
- K-MOOC
- Entity
- 블록체인 강의
- K-MOOC 단국대학교 홍보단
- 블록체인
- StringTokenizer
- stringreader
- 해시
- html기초
- 우선순위큐
- 시스템프로그래밍
- 자바문자열구분
- 단국대학교 k-mooc
- 자바스크립트
- 디스크블록할당
Archives
- Today
- Total
열정 실천
[JAVA] 미로찾기 문제 풀 땐 DFS보다 BFS with Queue 본문
728x90
오늘의 문제는 미로 찾기!!
미로 찾기는 ① 출발점에서 도착점까지 가는 최단거리를 찾는 문제이거나
② 출발점에서 도착점까지 갈 수 있는 경로의 개수를 세거나 하는 문제 인데
이번 백준 2178번 문제는 최단거리를 찾는 문제이다.
처음에 DFS로 문제를 풀었다.
DFS 문제 풀이
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class beakjoon_2178 {
static int[][] miro;
static boolean[][] visit;
static int min;
static int n;
static int m;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
miro = new int[n][m];
visit = new boolean[n][m];
min = n*m;
for(int i=0; i<n; i++){
String str = br.readLine();
for(int j=0; j<m; j++){
miro[i][j] = Integer.parseInt(String.valueOf(str.charAt(j)));
}
}
visit[0][0] = true;
dfs(0,0,1);
System.out.println(min);
}
static void dfs(int i, int j, int length){
if(i==n-1 && j==m-1){
if(min>length){
min = length;
}
}
else{
if(j+1<m){ //우
if(miro[i][j+1]==1 && !visit[i][j+1]){
visit[i][j+1] = true;
dfs(i, j+1, length+1);
visit[i][j+1] = false;
}
}
if(i+1<n){ //하
if(miro[i+1][j]==1 && !visit[i+1][j]){
visit[i+1][j] = true;
dfs(i+1, j, length+1);
visit[i+1][j] = false;
}
}
if(i-1>=0){ //상
if(miro[i-1][j]==1 && !visit[i-1][j]){
visit[i-1][j] = true;
dfs(i-1, j, length+1);
visit[i-1][j] = false;
}
}
if(j-1>=0){ //좌
if(miro[i][j-1]==1 && !visit[i][j-1]){
visit[i][j-1] = true;
dfs(i, j-1, length+1);
visit[i][j-1] = false;
}
}
}
}
}
그런데 시간초과가 나버렸땅! 😣
이 문제는 DFS가 아닌 BFS로 접근해야하는 문제였다.
우선 DFS와 BFS 탐색 방식의 차이는 이렇다
🤔 DFS와 BFS의 탐색 방식 차이
- DFS (깊이 우선 탐색):
- 한 경로를 끝까지 탐색한 후, 다시 돌아와 다른 경로를 탐색한다.
- 재귀 호출이나 스택을 사용해 "백트래킹(backtracking)"하며 경로를 탐색한다.
- 경로를 끝까지 탐색해야 하므로 비효율적인 경우가 많다.
- BFS (너비 우선 탐색):
- 가까운 노드부터 차례대로 탐색하며, 같은 레벨의 노드를 모두 확인한 후 다음 레벨로 이동한다.
- 최단 경로를 자연스럽게 찾으며, 탐색 깊이를 최소화한다.
😯 그래서 DFS가 더 오래 걸리는 이유
- 불필요한 경로 탐색:
- DFS는 모든 경로를 끝까지 탐색하기 때문에, 최적의 경로를 찾더라도 다른 모든 경로를 탐색해야 한다.
- 특히, 그래프의 노드가 많고 경로가 복잡할수록 DFS는 비효율적이다.
- 백트래킹의 비용:
- DFS는 잘못된 경로로 깊이 들어간 뒤, 다시 되돌아오는 과정(백트래킹)이 필요한데, 이 과정은 반복적으로 호출 스택을 사용하므로 시간 소모가 크다.
- 최단 경로를 바로 찾지 못함:
- BFS는 가까운 노드를 먼저 탐색하므로 최단 경로를 바로 찾을 가능성이 크다.
- 반면 DFS는 임의의 깊은 경로로 탐색하기 때문에 최단 경로를 바로 찾지 못할 가능성이 높다.😯😯😯😯
😊 BFS로 미로찾기 풀기
이는 거리를 저장하는 배열이다. 이 칸을 bfs로 하나씩 채워주는 것이 이 해답의 포인트!!
[0,0]부터 Queue에 넣은 뒤 하나씩 꺼내서 다음을 반복한다.
▶️ 상하좌우 중 1인 칸을 탐색하여 거리를 현재에서 +1해서 저장하고 해당 칸을 Queue에 넣어준다.
그럼 최종적으로 [n-1][m-1]인 칸의 거리가 최단 거리가 된다.
BFS 문제 풀이
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class beakjoon_2178 {
static int[][] miro;
static int[][] distance;
static int min;
static int n;
static int m;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
miro = new int[n][m];
distance = new int[n][m];
min = n*m;
for(int i=0; i<n; i++){
String str = br.readLine();
for(int j=0; j<m; j++){
miro[i][j] = Integer.parseInt(String.valueOf(str.charAt(j)));
}
}
distance[0][0] = 1;
Queue<int[]> queue = new LinkedList<>();
queue.add(new int[]{0,0}); //**큐안에 배열(좌표값)
while(!queue.isEmpty()) {
int[] cur = queue.poll();
int i = cur[0];
int j = cur[1];
if (i - 1 >= 0) { //상
if (miro[i - 1][j] == 1 && distance[i - 1][j] == 0) {
distance[i - 1][j] = distance[i][j] + 1;
queue.add(new int[]{i - 1, j});
}
}
if (i + 1 < n) { //하
if (miro[i + 1][j] == 1 && distance[i + 1][j] == 0) {
distance[i + 1][j] = distance[i][j] + 1;
queue.add(new int[]{i + 1, j});
}
}
if (j - 1 >= 0) { //좌
if (miro[i][j - 1] == 1 && distance[i][j - 1] == 0) {
distance[i][j - 1] = distance[i][j] + 1;
queue.add(new int[]{i, j - 1});
}
}
if (j + 1 < m) { //우
if (miro[i][j + 1] == 1 && distance[i][j + 1] == 0) {
distance[i][j + 1] = distance[i][j] + 1;
queue.add(new int[]{i, j + 1});
}
}
}
System.out.println(distance[n-1][m-1]);
}
}
오예!
앗 만약 출발점에서 도착점까지 갈 수 있는 경로의 개수를 묻는 문제가 나온다면
방문을 확인하는 과정을 생략하고 도착지에 도달할 때마다 COUNT+1을 해주면 될 것 같다!
728x90
'개발 공부 > 코딩 문제풀이' 카테고리의 다른 글
[알고리즘] 알고리즘 패러다임에 대해서 알아보자! (0) | 2025.01.09 |
---|---|
[알고리즘] 프로그래머스 연속된 부분 수열의 합 :: 투포인터 with JAVA (0) | 2025.01.07 |
[우선순위큐] 프로그래머스 42627 - 디스크 컨트롤러 with Java (2) | 2024.10.14 |
[JAVA] 프로그래머스 42578 의상 - 해시 자료구조, 조합 풀이 (0) | 2024.09.04 |
[JAVA] 프로그래머스 42577 전화번호 목록 (1) | 2024.09.03 |