[백준/Python] 2206 벽 부수고 이동하기

알고리즘 - 벽 부수고 이동하기

Posted by Kyun2da on September 22, 2020

1️⃣ 서론

백준 문제 2206번 벽 부수고 이동하기 입니다. 파이썬(Python)으로 풀었습니다.

2️⃣ 문제 설명

벽을 한개까지 부술 수 있을 때, 최단 경로를 구하는 문제입니다.

3️⃣ 풀이

벽을 부순 횟수가 1이므로 3차원 행렬을 통해 이를 표현할 수 있습니다.

[x][y][0] 칸은 벽을 아직 한번도 부순적이 없을 때의 최단 경로 횟수가 들어있습니다.

반면, [x][y][1] 칸은 벽을 이미 한번 부수고 왔을 때의 최단 경로 입니다.

이렇게 bfs로 다음 행렬을 탐색하며 최단 경로를 탐색하면 됩니다.

그럼 소스코드를 살펴보겠습니다.

4️⃣ 소스코드

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import sys
from collections import deque


def bfs():
    q.append([0, 0, 0])
    vis[0][0][0] = 1
    while q:
        x, y, z = q.popleft()
        for i in range(4):
            dx = x + dir[i][0]
            dy = y + dir[i][1]
            if 0 <= dx < n and 0 <= dy < m:
                # 아직 방문하지 않았고, 갈 수 있는 경우
                # 벽을 뚫고온 배열이면 벽을 뚫고온 배열에, 아니면 뚫고 오지 않은 배열에 1을더한다.
                if arr[dx][dy] == 0 and vis[dx][dy][z] == -1:
                    vis[dx][dy][z] = vis[x][y][z] + 1
                    q.append([dx, dy, z])
                # 벽을 뚫고오지 않은 배열이고 갈려는 곳에 벽이 있을 때
                elif z == 0 and arr[dx][dy] == 1 and vis[dx][dy][1] == -1:
                    vis[dx][dy][1] = vis[x][y][z] + 1
                    q.append([dx, dy, 1])


n, m = map(int, input().split())

arr = []
for _ in range(n):
    arr.append(list(map(int, sys.stdin.readline().rstrip())))

# 방문을 하지 않았다는 표시는 -1로 하고 여기에 최단 경로의 수가 저장이 됩니다.
vis = [[[-1] * 2 for _ in range(m)] for _ in range(n)]
# bfs로 돌 큐 선언
q = deque()
# 방향 탐색을 위한 dir 배열
dir = [[1, 0], [0, 1], [-1, 0], [0, -1]]

bfs()

# ans1은 벽을 한번도 뚫지 않고 왔을 때의 최단경로,
# ans2는 벽을 한번 뚫고 왔을 때의 최단경로가 저장됩니다.
ans1, ans2 = vis[n - 1][m - 1][0], vis[n - 1][m - 1][1]

if ans1 == -1 and ans2 != -1:
    print(ans2)
elif ans1 != -1 and ans2 == -1:
    print(ans1)
else:
    print(min(ans1, ans2))

5️⃣ 마치며..

질문과 지적은 환영합니다. 이 문제는 최적의 정답일 수도 아닐수도 있습니다.
궁금한게 있으시면 아래 댓글 남겨주세요.🙏
댓글은 저에게 큰 힘이 됩니다!
감사합니다. ❤️