728x90
[Java] 백준 2206 : 벽 부수고 이동하기
https://www.acmicpc.net/problem/2206
2206번: 벽 부수고 이동하기
N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로
www.acmicpc.net
접근
일반적인 bfs 방문체크에서 벽을 부수는 것을 옵션으로 추가해야하는 문제이다.
visted를 3차원 배열로 선언하여, x, y축과 벽을 부섰는지의 여부를 체크할 수 있도록 구현했다.
최초 방문체크를 할 때 벽을 아예 부수지 않는 탐색자와 벽을 한 번 부술 수 있는 탐색자로 나눈다.
visited[x][y][0] = true;
visited[x][y][1] = true;
벽에 도달했을 때 현재 탐색자가 벽을 부순 적이 없었고 벽을 부술 수 있는 탐색자가 방문을 한적이 없었다면 방문체크를 한다.
while (!q.isEmpty()) {
Node pick = q.poll();
// 목적지[n, m]에 도착시 count 출력하고 종료
if (pick.x == n-1 && pick.y == m-1) return pick.count;
큐에서 하나 뽑았을 때 좌표가 목적지와 같다면 시간이 얼마나 걸렸는지 반환하고 종료한다.
큐에 값이 다 비었을 때까지 반환되는 값이 없으면 -1을 반환한다.




코드
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 Main {
static int[] dx = {1, 0, -1, 0};
static int[] dy = {0, 1, 0, -1};
static int n, m;
static int[][] board;
static boolean[][][] visited;
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());
board = new int[n][m];
for (int i = 0; i < n; i++) {
String str = br.readLine();
for (int j = 0; j < m; j++) {
board[i][j] = (int) str.charAt(j) - '0';
}
}
visited = new boolean[n][m][2]; // 2는 벽 부섰는지(1) 안부섰는지(0) 체크 여부
System.out.println(bfs(0, 0));
}
private static int bfs(int x, int y) {
Queue<Node> q = new LinkedList<>();
q.add(new Node(x, y, 1, 0));
visited[x][y][0] = true;
visited[x][y][1] = true;
while (!q.isEmpty()) {
Node pick = q.poll();
// 목적지[n, m]에 도착시 count 출력하고 종료
if (pick.x == n-1 && pick.y == m-1) return pick.count;
for(int i = 0; i < 4; i++) {
int nx = pick.x + dx[i];
int ny = pick.y + dy[i];
if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
if(board[nx][ny] ==0) { // 벽 아닌 곳일 때
if (!visited[nx][ny][pick.wall]) {
q.add(new Node(nx, ny, pick.count + 1, pick.wall));
visited[nx][ny][pick.wall] = true;
}
}
else { // 벽인경우
if (pick.wall == 0 && !visited[nx][ny][1]) {
// 현 위치를 벅 부수고 방문처리한 적이 없고 벽을 부술 수 있는 탐색자가 방문한 적이 없을 경우
q.add(new Node(nx, ny, pick.count + 1, 1));
visited[nx][ny][1] = true; // 벽을 부수고 방문체크
}
}
}
}
}
return -1;
}
private static class Node {
private int x;
private int y;
private int count;
private int wall;
public Node(int x, int y, int count, int wall) {
this.x = x;
this.y = y;
this.count = count;
this.wall = wall;
}
}
}
728x90
'알고리즘 문제 풀이' 카테고리의 다른 글
[Java] 프로그래머스 : 로또의 최고 순위와 최저 순위 (0) | 2023.08.01 |
---|---|
[Java] 프로그래머스 : K번째 수 (0) | 2023.07.21 |
[Java] 백준 14226 : 이모티콘 (0) | 2023.07.20 |
[Java] 백준 1987 : 알파벳 (0) | 2023.07.13 |
[Java] 백준 2667 : 단지번호붙이기 (0) | 2023.07.13 |