코딩가딩가딩/BOJ

[BFS] 유형 이해하기:벽 부수고 이동하기/미로만들기

worldforest 2020. 10. 22. 01:47

시작부터 끝

최소 변경 👉 각 위치마다 변경 횟수 저장 (visit배열을 int형으로)

무한대로 초기화, 최소값을 저장

이 유형을 이해해서 비슷한 문제를 풀어보자.

 

public class Main {

	static class XY {
		int y;
		int x;
		int cnt;
		int punch;

		XY(int y, int x, int cnt, int punch) {
			this.y = y;
			this.x = x;
			this.cnt = cnt;
			this.punch = punch;
		}
	}
    
	static int N, M;
    static int[][] map;
	static boolean[][] visit;
    
    static int[] dy = { -1, 1, 0, 0 };
	static int[] dx = { 0, 0, -1, 1 };
    
	static int answer;

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
        // BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        // String[] str = in.readLine().split(" "); // 공백있는 한 줄 문자 하나씩 저장
		N = sc.nextInt();
		M = sc.nextInt();

		map = new int[N][M];
		visit = new boolean[N][M];
		for (int i = 0; i < N; i++) {
			String str = sc.next();
            // str = in.readLine().split(""); // 빈칸없는 문자열 문자하나씩 저장
			for (int j = 0; j < M; j++) {
				map[i][j] = str.charAt(j)-'0';
                visit[i][j] = Integer.MAX_VALUE; // 무한대로 초기화
			}
		}
        answer = Integer.MAX_VALUE;
        
		bfs(0, 0); // 출발점부터 시작
		System.out.print(answer);
	}

	private static void bfs(int y, int x) {
		Queue<XY> q = new LinkedList<>();
        // y좌표, x좌표, 전체 이동거리를 구하기 위한 이동횟수, 최소를 구하기 위한 변경횟수
		q.offer(new XY(y, x, 1, 0));// 시작점은 항상 0
        visit[y][x] = 0; // 처음 위치 변경횟수=0
        
		while (!q.isEmpty()) {
			XY curr = q.poll();
			int cy = curr.y;
			int cx = curr.x;
			int cnt = curr.cnt; // 이동
            int punch = curr.punch; // 변경
            
			if (cy == N-1 && cx == M-1) {// 도착점에 왔을 때
				answer = cnt;
				break;
			}
			for (int d = 0; d < 4; d++) {
				int ny = cy + dy[d];
				int nx = cx + dx[d];
                if(!cango(ny,nx)) continue; //범위 벗어날 때
                if(visit[ny][nx] <= punch) continue; // 변경횟수 초과할 때
                
                if (map[ny][nx] == 0) {// 변경없이 이동가능할 때
                	visit[ny][nx] = punch; //변경 안했으니까
                	q.offer(new XY(ny, nx, cnt++, punch));
                }
                else{// 변경해야 이동가능할 때
                	if(punch == 0){
                    	visit[ny][nx] = punch++;
                        q.offer(new XY(ny, nx, cnt++, punch++));
                    }
				}
			}
		}
	}

	private static boolean cango(int ny, int nx) {
		if (ny >= 0 && nx >= 0 && ny < N && nx < M) {
			return false;
		}
		return true;
	}
}

 

 

2206번: 벽 부수고 이동하기

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로

www.acmicpc.net

 

반응형