본문 바로가기
Problem Solving/BOJ

[Python]2206. 벽 부수고 이동하기

by 부르르 2019. 4. 2.

https://www.acmicpc.net/problem/2206

 

2206번: 벽 부수고 이동하기

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로로 이동하려 한다. 최단경로는 맵에서 가장 적은 개수의 칸을 지나는 경로를 말하는데, 이때 시작하는 칸과 끝나는 칸도 포함해서 센다. 만약에 이동하는 도중에 한 개의 벽을 부수고 이동하는 것이 좀 더 경로가 짧아진다면, 벽을 한 개 까지 부수고 이동

www.acmicpc.net


 

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
from collections import deque
 
dr = ((-1,0), (1,0), (0,-1), (0,1))
 
def bfs(y,x,k):
    global n, m
    queue = deque()
    queue.append((y,x,k)) # k 는 전체 맵에서 어떤 벽이 한번 부숴진 상태를 나타낸다. k=0 부숴지기 전 k=부숴진 후
    dist[y][x][k] = 1
    while queue:
        curr_y, curr_x, status = queue.popleft()
        for d in dr:
            next_y, next_x = curr_y+d[0], curr_x+d[1]
            if 0<=next_y<and 0<=next_x<m:
                if MAP[next_y][next_x] == 0 and dist[next_y][next_x][status] == 0# 평지이고 주변 벽이 (부숴지기 전/부숴진 후) 방문한적 없다면
                        dist[next_y][next_x][status] = dist[curr_y][curr_x][status]+1
                        queue.append((next_y,next_x,status))
 
                if status == 0# 평지든 벽이든 부숴진 벽이 없을 때
                    if MAP[next_y][next_x] == 1 and dist[next_y][next_x][status + 1== 0# 벽이고 벽이 부숴진적 없다면(= 부숴지고 방문안했다면)
                            dist[next_y][next_x][status+1= dist[curr_y][curr_x][status] + 1
                            queue.append((next_y, next_x, status+1))
 
n, m = map(int, input().split())
MAP = [list(map(int, input())) for _ in range(n)]
dist = [[[0]*2 for _ in range(m)] for _ in range(n)]
bfs(0,0,0)
 
if dist[n-1][m-1][0!= 0 and dist[n-1][m-1][1]  != 0# 부숴지기 전과 후를 비교해서 작은 것을 출력
    print(min(dist[n-1][m-1]))
elif dist[n-1][m-1][0!= 0# 부숴지기 전만 값이 있다면 부숴지기 전만 출력
    print(dist[n-1][m-1][0])
elif dist[n-1][m-1][1!= 0# 부숴진 후만 값이 있다면 부숴진 후만 출력
    print(dist[n-1][m-1][1])
else:
    print(-1# 둘다 값이 없다면 도달할 수 없는 것이므로 -1 출력
 
'''
보충설명
dist[i][i][0] = 벽이 부숴진 것 없이 자기 자신의 위치에 도달하는 최단경로
dist[i][i][1] = 벽이 부숴진 후 자기 자신의 위치에 도달하는 최단경로
dist[i][j][0] = 벽이 부숴진 것 없이 i에서 j 위치에 도달하는 최단경로
dist[i][j][1] = 벽이 부숴진 후 i에서 j 위치에 도달하는 최단경로
'''
'''
# input
6 9
010001000
010001010
010101010
010101000
010101010
000100010
# ouput
18
'''
'''
출처: https://www.acmicpc.net/board/view/27386
"현재 상태" 자체를 큐에 넣어서 문제를 풀어야 합니다. 
즉, 어떤 좌표에 있는가 뿐만 아니라, "여기까지 오면서 벽을 부순 적이 있는가" 여부를 함께 큐에 저장해서 탐색하고, 
각각을 별개로 방문 체크해줘야 하는 문제입니다. visited[x][y]가 아니라, visited[x][y][벽을 부순 적이 있는가?] 가 되어야 합니다.
'''
cs
728x90
반응형

'Problem Solving > BOJ' 카테고리의 다른 글

[Python]1463. 1로 만들기  (0) 2019.04.02
[Python]3055. 탈출  (0) 2019.04.02
[Python]1261. 알고스팟  (0) 2019.04.02
[Python]13549. 숨바꼭질 3  (0) 2019.04.01
[Python]14226. 이모티콘  (0) 2019.04.01

댓글