λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
⭐ Problem_Solving/λ°±μ€€

[λ°±μ€€] 2206 λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ° (Python/파이썬)

by ν¬μŠ€νŠΈμ‰μ΄ν¬ 2022. 9. 27.

<문제 링크>

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

 

2206번: λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ°

N×M의 ν–‰λ ¬λ‘œ ν‘œν˜„λ˜λŠ” 맡이 μžˆλ‹€. λ§΅μ—μ„œ 0은 이동할 수 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚΄κ³ , 1은 이동할 수 μ—†λŠ” 벽이 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚Έλ‹€. 당신은 (1, 1)μ—μ„œ (N, M)의 μœ„μΉ˜κΉŒμ§€ μ΄λ™ν•˜λ € ν•˜λŠ”λ°, μ΄λ•Œ μ΅œλ‹¨ 경둜

www.acmicpc.net

<풀이 μ „λž΅>

  1. 벽을 λΆ€μˆ˜λŠ” κ±Έ κ΅¬ν˜„ν•˜λŠ” 게 핡심이닀.
  2. 일반적인 2차원 배열에 λ²½ λΆ€μˆ˜λŠ” κ±Έ λ‚˜νƒ€λ‚΄μ£ΌλŠ” λ³€μˆ˜λ₯Ό μΆ”κ°€μ μœΌλ‘œ λ„£μ–΄μ„œ bfsλ₯Ό 돌리면 μ—λŸ¬κ°€ λ‚œλ‹€.
    • νŠΉμ • 지점 (r, c)에 벽을 λΆ€μˆ˜κ³  λ„λ‹¬ν•˜λŠ” 방법(a)λž‘ 벽을 λΆ€μˆ˜μ§€ μ•Šκ³  λ„λ‹¬ν•˜λŠ” 방법(b)κ°€ μžˆλŠ”λ°, aκ°€ b보닀 거리가 짧을 λ•Œ(a < b)일 λ•Œ 2차원 λ°°μ—΄μ—μ„œλŠ” a만 ν‘œμ‹œ λœλ‹€.
    • κ·ΈλŸ¬λ‹€ λ‚˜μ€‘μ— 벽을 λΆ€μˆ˜μ§€ μ•Šκ³ λŠ” ν†΅κ³Όν•˜μ§€ λͺ»ν•˜λŠ” 상황이 λ°œμƒν•  λ•Œ 이미 벽을 λΆ€μ…¨κΈ° λ•Œλ¬Έμ—(a) 톡과λ₯Ό λͺ»ν•˜κ³  -1을 λ°˜ν™˜ν•˜κ²Œ λ˜λŠ”λ°, 사싀 b 루트둜 μ™”μœΌλ©΄ 톡과할 수 μžˆλŠ” 길이닀.

3. λ”°λΌμ„œ 벽을 λΆ€μˆ˜μ§€ μ•Šμ€ λ°°μ—΄κ³Ό 벽을 λΆ€μˆ˜μ§€ μ•Šμ€ λ°°μ—΄ 두 배열을 λ‹΄μ•„μ„œ 3차원 λ°°μ—΄λ‘œ ν‘œν˜„ν•˜κ³  bfsλ₯Ό λŒλ €μ•Ό ν•œλ‹€. λ§Œν™”λ‚˜ μ˜ν™”μ—μ„œ 선택에 따라 세계선이 λ‚˜λ‰˜λŠ” 그런 λŠλ‚ŒμœΌλ‘œ μ΄ν•΄ν•˜λ©΄ λœλ‹€.

4. 3차원 배열을 λ§Œλ“€ λ•Œ μ£Όμ˜ν•΄μ•Όν•  점은 arr이 기본적으둜 2차원 배열이기 λ•Œλ¬Έμ— ν• λ‹Ήμ΄λ‚˜ κ·Έλƒ₯ 볡사가 μ•„λ‹ˆλΌ deepcopyλ₯Ό μ΄μš©ν•œ κΉŠμ€ 볡사λ₯Ό ν•΄μ€˜μ•Ό ν•œλ‹€.

5. μ—¬κΈ°κΉŒμ§€ ν–ˆμœΌλ©΄ 벽을 뢀셨을 λ•Œ 차원이 μ΄λ™ν•˜λŠ” κ²ƒλ§Œ μ‹ κ²½μ¨μ„œ bfsλ₯Ό κ΅¬ν˜„ν•΄μ£Όλ©΄ λœλ‹€.

 

<μ •λ‹΅ μ½”λ“œ>

# 220827 2206 λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ°

# μ •λ‹΅μ½”λ“œ

from collections import deque
from copy import deepcopy
import sys
intput = sys.stdin.readline

# N: ν–‰μ˜ 개수, M: μ—΄μ˜ 개수
N, M = map(int, input().split())

# arr: 맡, arr2: arr의 볡사본 (2차원 λ°°μ—΄μ΄λ―€λ‘œ deepcopy)
arr = [list(map(int, input())) for _ in range(N)]
arr2 = deepcopy(arr)
# arr_3d: 맡의 3차원 λ°°μ—΄ (0: λ²½ μ•ˆ λΆ€μˆ¨, 1: λ²½ λΆ€μˆ¨)
arr_3d = [arr, arr2]

# 탐색 λ°©ν–₯
dr = [-1, 1, 0, 0]
dc = [0, 0, -1, 1]


# 3차원 bfs ν•¨μˆ˜ μ„ μ–Έ
def bfs(z, r, c):

    # 좜발점 ν‘œμ‹œ
    arr_3d[z][r][c] = 1
    
    # queue: μ’Œν‘œλ₯Ό 담을 큐
    queue = deque()
    queue.append((z, r, c))
    
    while queue:
        z, r, c = queue.popleft()
        
        # λͺ©ν‘œ 지점 도착 μ‹œ 거리 좜λ ₯ ν›„ λ°˜ν™˜
        if r == N - 1 and c == M - 1:
            print(arr_3d[z][r][c])
            return

        # 4λ°©ν–₯ 탐색
        for i in range(4):
            nr = r + dr[i]
            nc = c + dc[i]
            # 탐색 λ°©ν–₯이 인덱슀 λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜μ§€ μ•Šμ„ λ•Œ
            if 0 <= nr < N and 0 <= nc < M:

                # 벽이 μžˆμ„ 경우
                if arr_3d[z][nr][nc] == 1:
                    # 아직 벽을 λΆ€μˆ˜μ§€ μ•Šμ•˜μ„ 경우 벽을 λΆ€μˆ˜κ³  벽을 λΆ€μˆœ μ°¨μ›μœΌλ‘œ λ„˜μ–΄κ°€μ„œ 탐색을 μ§„ν–‰ν•œλ‹€.
                    if z == 0:
                        arr_3d[1][nr][nc] = arr_3d[0][r][c] + 1
                        queue.append((1, nr, nc))
                
                # 벽이 없을 경우 ν˜„μž¬ μ°¨μ›μ—μ„œ κ·ΈλŒ€λ‘œ 탐색을 μ§„ν–‰ν•œλ‹€.
                elif arr_3d[z][nr][nc] == 0:
                    arr_3d[z][nr][nc] = arr_3d[z][r][c] + 1
                    queue.append((z, nr, nc)) 
    
    # λͺ©ν‘œ 지점에 λ„μ°©ν•˜μ§€ λͺ»ν–ˆμ„ 경우 -1 좜λ ₯ ν›„ λ°˜ν™˜
    print(-1)
    return

# bfs 탐색 μ‹€μ‹œ
bfs(0, 0, 0)

λŒ“κΈ€