본문 바로가기
백준

백준 14442번 : 벽 부수고 이동하기 2

by Huiyeong 2021. 4. 10.

 문제

www.acmicpc.net/problem/14442

 

14442번: 벽 부수고 이동하기 2

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000), K(1 ≤ K ≤ 10)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다. (1, 1)과 (N, M)은 항상 0이라고 가정하자.

www.acmicpc.net

14442 벽 부수고 이동하기 2

 

 구현 방법

 벽을 한 개까지 부수고 이동할 수 있기 때문에 방문을 관리하는 visited 배열을 3차원으로 선언하여 좌표와 벽을 부술 수 있는지에 대한 여부를 관리해줍니다. 상하좌우를 검사하여 빈 칸이 일 때에는 그냥 지나가고 벽일 때 현재 좌표에서 벽을 부술 수 있다면 벽을 부수고 지나가줍니다. 이동을 하다가 (N, M) 좌표까지 가게 된다면 반복문을 끝내주고 거리를 리턴, 반복문이 그대로 끝난다면 불가능하므로 -1을 출력해줍니다.

 

 구현 코드

package BOJ.Gold;

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 BOJ14442_벽부수고이동하기2 {
	static int R, C, K, cnt;
	static boolean[][][] visited;
	static int[][] map, deltas= {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
	static Queue<Move> queue;
	static class Move {
		int r, c, wallB;

		public Move(int r, int c, int wallB) {
			super();
			this.r = r;
			this.c = c;
			this.wallB = wallB;
		}	
	}
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		R = Integer.parseInt(st.nextToken());
		C = Integer.parseInt(st.nextToken());
		K = Integer.parseInt(st.nextToken());
		map = new int[R][C];
		visited = new boolean[R][C][K+1];
		for (int r=0;r<R;r++) {
			String input = br.readLine();
			for (int c=0;c<C;c++) {
				map[r][c] = input.charAt(c)-'0';
			}
		}
		// 입력완료
		queue = new LinkedList<>();
		queue.offer(new Move(0, 0, 0));
		visited[0][0][0] = true;
		cnt = 1;
		boolean flag = bfs();
		if (flag) System.out.println(cnt);
		else System.out.println(-1);
	}
	
	static boolean bfs() {
		while(!queue.isEmpty()) {
			int size = queue.size();
			for (int i=0;i<size;i++) {
				Move now = queue.poll();
				if (now.r==R-1 && now.c==C-1) return true;
				for (int d=0;d<4;d++) {
					int nr = now.r+deltas[d][0];
					int nc = now.c+deltas[d][1];
					if (isIn(nr, nc)) {
						if (map[nr][nc]==0 && !visited[nr][nc][now.wallB]) {
							visited[nr][nc][now.wallB] = true;
							queue.offer(new Move(nr, nc, now.wallB));
						} else if (map[nr][nc]==1 && now.wallB<K && !visited[nr][nc][now.wallB+1]) {
							visited[nr][nc][now.wallB+1] = true;
							queue.offer(new Move(nr, nc, now.wallB+1));
						}
					}
				}
			}
			cnt++;
		}
		
		return false;
	}
	
	static boolean isIn(int nr, int nc) {
		return nr>=0 && nr<R && nc>=0 && nc<C;
	}
}

 

정답!

'백준' 카테고리의 다른 글

백준 9081번 : 단어 맞추기  (0) 2021.07.06
백준 9935번 : 문자열 폭발  (0) 2021.07.05
백준 2206번 : 벽 부수고 이동하기  (0) 2021.04.09
백준 16953번 : A -> B  (0) 2021.04.09
백준 1755번 : 숫자놀이  (0) 2021.04.09