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 |
Tags
- 그리디
- 링크드리스트
- 분할 정복
- SSAFY
- 순열
- 중복 순열
- 우선순위 큐
- 클래스
- 빠른 입출력
- 메모리풀
- 비트마스크
- dfs
- 크루스칼
- 이분 탐색
- 큐
- Knapsack
- 완전 탐색
- 세그먼트 트리
- DP
- 조합
- 스택
- lis
- 재귀
- 문자열
- 피보나치 수
- 시뮬레이션
- BFS
- 백트래킹
- BeautifulSoup
- MST
Archives
- Today
- Total
작심 24/7
[백준] 2206번 벽 부수고 이동하기 (JAVA) 본문
2206번: 벽 부수고 이동하기
N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로
www.acmicpc.net
최단 거리를 구하는 문제이므로 BFS를 쓰는 게 적합하다.
일단 큐에는 x, y좌표 뿐만 아니라
현재까지의 이동 횟수,
이전에 벽을 부쉈는지의 여부
도 저장해주어야 한다.
벽을 한 번만 부술 수 있기 때문에
이전에 벽을 부순 적이 있으면
그 루트는 앞으로 벽을 뚫고 지나가지 못 한다.
그리고 방문 체크를 해줄 때
벽을 한 번 부순 경우와
벽을 부수지 않은 경우
두 가지로 나누어서 체크해주어야 하기 때문에
3차원 배열 visited를 사용해서
[벽 부쉈는지 유무(0 or 1)][x좌표][y좌표]
로 인덱스를 사용해 주었다.
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class BOJ_2206_벽_부수고_이동하기 {
private static int N, M, res = -1;
private static int arr[][], dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
private static boolean visited[][][];
private static Queue <int[]> q = new LinkedList<>();
public static void bfs() {
visited[0][0][0] = true;
q.offer(new int[] {0, 0, 1, 0}); // x, y, 이동 횟수, 이전에 벽 부쉈으면 1 아니면 0
while(!q.isEmpty()) {
for(int i = 0; i < 4; i++) {
int x = q.peek()[0] + dx[i], y = q.peek()[1] + dy[i], crash = q.peek()[3];
if(x < 0 || x >= N || y < 0 || y >= M || visited[crash][x][y]) continue;
if(x == N - 1 && y == M - 1) {
res = q.peek()[2] + 1; // 탈출 성공
return;
}
if(arr[x][y] == 1) { // 벽이 가로막고 있을 때
if(crash == 1) continue; // 이미 이전에 벽을 부쉈으면 넘어감
crash = 1; // 벽을 부숴버림
}
visited[crash][x][y] = true; // 벽 부순 경로와 벽 안 부순 경로가 겹치지 않게
q.offer(new int[] {x, y, q.peek()[2] + 1, crash});
}
q.poll();
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt(); M = sc.nextInt();
arr = new int[N][M]; visited = new boolean[2][N][M];
for(int i = 0; i < N; i++) {
String st = sc.next();
for(int j = 0; j < M; j++) arr[i][j] = st.charAt(j) - '0';
}
bfs();
if(N == 1 && M == 1) System.out.println(1);
else System.out.println(res);
}
}
'백준' 카테고리의 다른 글
[백준] 13460번 구슬 탈출 2 (C++) - 2 (0) | 2021.04.23 |
---|---|
[백준] 1082번 방 번호 (JAVA) (0) | 2021.03.04 |
[백준] 9466번 텀 프로젝트 (JAVA) (0) | 2021.02.13 |
[백준] 2493번 탑 (JAVA) (0) | 2021.02.07 |
[백준] 3085번 사탕 게임 (JAVA) (0) | 2021.02.03 |
Comments