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

[λ°±μ€€] 17142 μ—°κ΅¬μ†Œ 3 (Python/파이썬)

by ν¬μŠ€νŠΈμ‰μ΄ν¬ 2022. 10. 7.

<문제 링크>

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

 

17142번: μ—°κ΅¬μ†Œ 3

인체에 치λͺ…적인 λ°”μ΄λŸ¬μŠ€λ₯Ό μ—°κ΅¬ν•˜λ˜ μ—°κ΅¬μ†Œμ— μŠΉμ›μ΄κ°€ μΉ¨μž…ν–ˆκ³ , λ°”μ΄λŸ¬μŠ€λ₯Ό μœ μΆœν•˜λ €κ³  ν•œλ‹€. λ°”μ΄λŸ¬μŠ€λŠ” ν™œμ„± μƒνƒœμ™€ λΉ„ν™œμ„± μƒνƒœκ°€ μžˆλ‹€. κ°€μž₯ μ²˜μŒμ— λͺ¨λ“  λ°”μ΄λŸ¬μŠ€λŠ” λΉ„ν™œμ„± μƒνƒœμ΄κ³ 

www.acmicpc.net

<풀이 μ „λž΅>

1. μ—°κ΅¬μ†Œ 2λž‘ 맀우 μœ μ‚¬ν•˜λ‚˜ λΉ„ν™œμ„± λ°”μ΄λŸ¬μŠ€μ˜ μ²˜λ¦¬κ°€ 생각보닀 κΉŒλ‹€λ‘­λ‹€

2. ν™œμ„±λ°”μ΄λŸ¬μŠ€μ™€ λ§Œλ‚˜λ©΄ ν™œμ„± μƒνƒœλ‘œ λ³€ν•˜λ‹ˆ '1'의 μ„±μ§ˆμ„ κ°€μ§€λ©΄μ„œ, λ™μ‹œμ— ν™•μ‚° μ‹œκ°„μ—λŠ” 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠμœΌλ―€λ‘œ '0'의 μ„±μ§ˆμ„ κ°€μ§€κ²Œ λœλ‹€.

3. μ—¬λŸ¬κ°€μ§€ 방법이 μžˆκ² μ§€λ§Œ λ‚˜ 같은 κ²½μš°λŠ” λΉ„ν™œμ„± -> ν™œμ„± λ°”μ΄λŸ¬μŠ€μ˜ μ’Œν‘œλ₯Ό μ €μž₯ν•˜λ©΄μ„œ νƒμƒ‰ν•˜λ‹€κ°€ λ§ˆμ§€λ§‰μ— 0으둜 μ΄ˆκΈ°ν™”ν•΄μ€ŒμœΌλ‘œμ¨ ν™•μ‚° μ‹œκ°„ 계산에 영ν–₯을 μ•ˆ λ―ΈμΉ˜λ„λ‘ ν–ˆλ‹€.

 

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

from collections import deque
from itertools import combinations
import sys, os, io, atexit

input = lambda: sys.stdin.readline().rstrip('\r\n')
stdout = io.BytesIO()
sys.stdout.write = lambda s: stdout.write(s.encode("ascii"))
atexit.register(lambda: os.write(1, stdout.getvalue()))

# 220924 17142 μ—°κ΅¬μ†Œ 3

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

# 델타 탐색 λ°©ν–₯ μ„€μ •
dr = [-1, 1, 0, 0]
dc = [0, 0, -1, 1]

# λ°”μ΄λŸ¬μŠ€ ν™•μ‚° bfs
def bfs(queue):
    # ν™œμ„± μƒνƒœλ‘œ λ³€ν•œ λΉ„ν™œμ„± λ°”μ΄λŸ¬μŠ€λ₯Ό 담을 리슀트
    activated = []

    while queue:
        r, c = queue.popleft()

        for i in range(4):
            nr = r + dr[i]
            nc = c + dc[i]
            if 0 <= nr < N and 0 <= nc < N:
                # 빈 곡간이면 λ°”μ΄λŸ¬μŠ€ ν™•μ‚°
                if arr_copy[nr][nc] == -10:
                    arr_copy[nr][nc] = arr_copy[r][c] + 1
                    queue.append((nr, nc))

                # λΉ„ν™œμ„± λ°”μ΄λŸ¬μŠ€μΌ 경우 일단 λ°”μ΄λŸ¬μŠ€ ν™•μ‚° ν›„ λ¦¬μŠ€νŠΈμ— λ‹΄μ•„μ€€λ‹€.
                if arr_copy[nr][nc] == -2:
                    arr_copy[nr][nc] = arr_copy[r][c] + 1
                    activated.append((nr, nc))
                    queue.append((nr, nc))
                    
    # 빈 곡간이 λ‚¨μ•„μžˆμ„ 경우
    for r in range(N):
        for c in range(N):
            if arr_copy[r][c] == -10:
                return sys.maxsize   

    # λΉ„ν™œμ„± -> ν™œμ„± λ°”μ΄λŸ¬μŠ€λ“€μ„ 0으둜 μ΄ˆκΈ°ν™” μ‹œμΌœμ€˜μ„œ ν™•μ‚° μ‹œκ°„μ„ κ²Œμ‚°μ— 영ν–₯을 μ•ˆ λ―ΈμΉ˜λ„λ‘ ν•œλ‹€
    for row, col in activated:
        arr_copy[row][col] = 0

    # ν™•μ‚° μ‹œκ°„ λ°˜ν™˜
    return max(map(max, arr_copy))



# N: μ—°κ΅¬μ†Œμ˜ 크기, M: λ°”μ΄λŸ¬μŠ€μ˜ 개수
N, M = map(int, input().split())
# arr: μ—°κ΅¬μ†Œ μƒνƒœ
arr = [list(map(int, input().split())) for _ in range(N)]
# virus: λ°”μ΄λŸ¬μŠ€λ₯Ό 놓을 μœ„μΉ˜
virus = []

# 빈 곡간을 -10으둜 μ΄ˆκΈ°ν™”ν•΄μ£Όκ³  λ°”μ΄λŸ¬μŠ€μ˜ μœ„μΉ˜λ₯Ό λ‹΄μ•„μ€€λ‹€.
for r in range(N):
    for c in range(N):
        if arr[r][c] == 0:
            arr[r][c] = -10
        if arr[r][c] == 1:
            arr[r][c] = -1
        if arr[r][c] == 2:
            arr[r][c] = -2
            virus.append((r, c))

# ans: λ°”μ΄λŸ¬μŠ€ 전체 ν™•μ‚° μ‹œκ°„ (μΆ©λΆ„νžˆ 큰 κ°’μœΌλ‘œ μ΄ˆκΈ°ν™”)
ans = sys.maxsize

# λ°”μ΄λŸ¬μŠ€λ₯Ό 놓을 μœ„μΉ˜λ₯Ό κ³ λ₯Έλ‹€.
for comb in combinations(virus, M):
    # arr_copy: bfs νƒμƒ‰μš© λ°°μ—΄ 볡사본
    arr_copy = [arr[i][:] for i in range(N)]

    # λ°”μ΄λŸ¬μŠ€μ˜ μœ„μΉ˜ 큐에 λ‹΄μ•„μ£ΌκΈ°
    queue = deque()
    for loc in comb:
        queue.append(loc)
        r, c = loc
        arr_copy[r][c] = 0

    # μ •λ‹΅ κ°±μ‹ ν•΄κ°€λ©΄μ„œ bfs 탐색
    ans = min(bfs(queue), ans)

# λ‹€ ν™•μ‚° μ‹œν‚€μ§€ λͺ»ν•  경우 -1 좜λ ₯
if ans == sys.maxsize:
    print(-1)
# μ •λ‹΅ 좜λ ₯
else:
    print(ans)

λŒ“κΈ€