ZZANZU/acmicpc

2178번 / 미로 탐색 / DFS

Opened this issue · 0 comments

https://www.acmicpc.net/problem/2178

2

우선은 DFS로 풀어봄.

	static int[] dx = {-1, 1, 0, 0};
	static int[] dy = {0, 0, -1, 1};
...
		// 2. 연결된 길을 찾는다.(상하좌우, 4가지) dx, dy를 사용하는 것에 집중!
		for(int i = 0; i < 4; i++) {
			int targetX = x + dx[i];
			int targetY = y + dy[i];
			
  • 한 위치에서 상,하,좌,우를 탐색하기 위해 현재 위치 (x, y)에 미리 정의한 탐색 좌표 이동거리 dx, dy를 정의해서 for문안에서 탐색

  • 채점 상으로는 시간 초과

기존 코드

package example02;

import java.util.Arrays;
import java.util.Scanner;

public class Problem2178 {
	static int N, M;
	static int[][] map;
	static boolean[][] visited;
	static int[] dx = {-1, 1, 0, 0};
	static int[] dy = {0, 0, -1, 1};
	static int min = Integer.MAX_VALUE;
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		N = sc.nextInt();
		M = sc.nextInt();
		sc.nextLine();
		
		// 그래프의 노드의 번호가 1,2,3 이런게 아니라서 그냥 N,M 써줌
		map = new int[N][M];
		visited = new boolean[N][M];
		
		// 여기서 int로 String의 한 글자를 받아보는 방식 ㅇㅇ
		for(int y = 0; y < N; y++) {
			String temp = sc.nextLine();
			
			for(int x = 0; x < M; x++) {
				if(temp.charAt(x) == '1') {
					map[y][x] = 1;
				} else {
					map[y][x] = 0;
				}
			}
		}
		
		dfs(0, 0, 1);
		System.out.println(min);
	}
	
	public static void dfs(int x, int y, int current) {
		// 0. 목적지 도달 여부 체크 , 이 부분을 생각 못함!
		if(y == N-1 && x == M-1) {
			if(current < min) {
				min = current;
			}
			return; // 쓸데없는 길 탐색 안하게 해줌
		}
		// 1. 방문 기록을 남긴다.
		visited[y][x] = true;
		
		// 2. 연결된 길을 찾는다.(상하좌우, 4가지) dx, dy를 사용하는 것에 집중!
		for(int i = 0; i < 4; i++) {
			int targetX = x + dx[i];
			int targetY = y + dy[i];
			
			if(targetX >= 0 && targetX < M && targetY >= 0 && targetY < N) {
				// 3. 갈 수 있는 길을 찾는다.
				if(map[targetY][targetX] == 1 && visited[targetY][targetX] == false){
					// 4. 간다
					dfs(targetX, targetY, current+1);
				}				
			}
		}
		// 5. 방문 해지
		visited[y][x] = false;
	}

}

근데 여기서 visited를 int형으로 바꿔서 각 칸이 방문이 되었을 때 거기를 지나간 당시의 거리(current)를 저장하게 된다. 그러면 다음번에 그 칸을 지나가게 되었을 때의 current와 visited(이전의 방문시 거리)를 비교한다.

public static void dfs(int x, int y, int current) {
		// 0. 목적지 도달 여부 체크 , 이 부분을 생각 못함!
		if(y == N-1 && x == M-1) {
			if(current < min) {
				min = current;
			}
			return; // 쓸데없는 길 탐색 안하게 해줌
		}
		// 1. 방문 기록을 남긴다.
		visited[y][x] = current;
		
		// 2. 연결된 길을 찾는다.(상하좌우, 4가지) dx, dy를 사용하는 것에 집중!
		for(int i = 0; i < 4; i++) {
			int targetX = x + dx[i];
			int targetY = y + dy[i];
			
			if(targetX >= 0 && targetX < M && targetY >= 0 && targetY < N) {
				// 3. 갈 수 있는 길을 찾는다.
				if(map[targetY][targetX] == 1){
					if(visited[targetY][targetX] == 0 || visited[targetY][targetX] > current+1)
					// 4. 간다
					dfs(targetX, targetY, current+1);
				}				
			}
		}
		// 5. 방문 해지
//		visited[y][x] = 0;
	}
  • '1. 방문 기록을 남긴다' 단계에서 방문 여부를 저장하는 것이 아니라, 해당 위치까지의 거리를 저장한다
    그렇게 되면 다음번에 해당 위치를 다시 한 번 방문하게 되었을 때, 이 값(visited)을 current와 비교하여 탐색을 더 할지 결정하게 된다.

  • 방문 해지는 하지 않는다!