Algorithm(BOJ, Python)/BFS&DFS

[백준_7576] 토마토 python

kurooru 2022. 8. 18. 13:29

오늘 배운 점 : bfs 동시에 돌릴 수 있다. (좌표를 다 큐에 때려놓고 시작하면 된다.)

# m, n 입력
m, n = map(int, input().split())

# storage
storage = [
    list(map(int, input().split()))
    for _ in range(n)
]

# in_range(x, y):
def in_range(x, y):
    return 0 <= x and x < n and 0 <= y and y < m

# can_go(x, y)
def can_go(x, y):
    # 범위 내에 없으면
    if not in_range(x, y):
        # 실패
        return False
    # 빈칸이면
    if storage[x][y] == -1:
        # 실패
        return False
    # 방문한 칸이면
    if visited[x][y] == 1:
        # 실패
        return False
    # 이외에는 성공
    return True

# bfs()
def bfs():
    while q:
        # 언팩킹
        x, y = q.popleft()

        # dxs, dys 상 하 좌 우 순서 상관 x
        dxs, dys = [-1, 1, 0, 0], [0, 0, 1, -1]
        for dx, dy in zip(dxs, dys):
            # 다음 조사 위치
            nx, ny = x + dx, y + dy
            # 갈 수 있으면,
            if can_go(nx, ny):
                # 방문표시 해주고,
                visited[nx][ny] = 1
                # 큐에 넣어주고,
                q.append((nx, ny))
                # step 배열 관리
                step[nx][ny] = step[x][y] + 1

# all_tomato()
def all_tomato():
    for i in range(n):
        for j in range(m):
            if storage[i][j] == 0:
                return False
    return True

# blocked()
def blocked():
    for i in range(n):
        for j in range(m):
            # 저장고의 값이 0이고 step의 값이 0이면,
            if storage[i][j] == 0 and step[i][j] == 0:
                # 막힌것임
                return True
    return False

# 설계

# visited (방문 기록을 해 줄 배열)
visited = [
    [0] * m
    for _ in range(n)
]

# step (시간을 기록 해 줄 배열)
step = [
    [0] * m
    for _ in range(n)
]

# 큐 사용 준비
from collections import deque

# 큐
q = deque()

# tomato_pos
tomato_pos = []

# storage를 돌면서
for i in range(n):
    for j in range(m):
        # 토마토를 만나면
        if storage[i][j] == 1:
            # 위치 기록
            tomato_pos.append((i, j))

# 익은 토마토들의 위치들을 모두 큐에 넣어주기
for tomato in tomato_pos:
    # 언팩킹
    x, y = tomato
    # 방문 처리
    visited[x][y] = 1
    # 큐에 넣어주고
    q.append((x, y))
# bfs 돌려주기
bfs()

# 모든 토마토가 익어있는 상태일 경우
if all_tomato():
    # 0 출력
    print(0)

# 토마토가 모두 익지 못하는 상황이면
elif blocked():
    # -1 출력
    print(-1)

# 이외의 상황 즉, 일반적인 상황
else:
    # 정답용
    ans = 0

    # step 돌면서
    for i in range(n):
        for j in range(m):
            # 최댓값을 찾으면
            if step[i][j] > ans:
                # 최댓값 갱신
                ans = step[i][j]
    # 출력
    print(ans)