[ 1. 음료수 얼려먹기 ]
강의 자료에서 재귀로 너무 간단하게 풀어버려서 Stack으로 풀기 도전
# DFS/BFS 문제 1 : 음료수 얼려먹기
# N × M 크기의 얼음 틀이 있습니다.
# 얼음 틀의 각 칸은
# 0 : 구멍이 뚫려 있어 물이 들어갈 수 있는 부분
# 1 : 칸막이가 존재하는 부분으로 표시됩니다.
# 구멍(0)이 상·하·좌·우로 서로 맞닿아 있으면 하나의 연결된 영역(덩어리)으로 간주합니다.
# 얼음 틀의 모양이 주어졌을 때, 얼려서 생성되는 아이스크림의 총 개수(= 0으로 이루어진 연결 요소의 수)를 구하세요.
def chunk(x, y, arr, visited):
moves = [(-1, 0), (1, 0), (0, -1), (0, 1)]
stack = [(x,y)]
chk = False
# 출발점이 1이거나 방문했던 곳이면 그냥 chk는 false로 넘기기
if arr[x][y] == 1 or visited[x][y]:
return visited, False
while stack:
(x,y) = stack.pop()
# 일단 하나를 뽑았고, 1이 아닌 값이므로, 한 chunk로 인식 chk = True
chk = True
visited[x][y] = True
# 범위를 넘어가면 넘기기
for dx, dy in moves:
if (0>(x+dx) or (x+dx)>n-1) or (0>(y+dy) or (y+dy)>m-1):
continue
# 해당 좌표가 1이거나 방문 했으면 넘기기
if arr[x+dx][y+dy] or visited[x+dx][y+dy]:
continue
# 범위를 안넘어 갔고 0인것을 확인했으니 상하좌우를 스택 추가
stack.append([x+dx, y+dy])
# 한 청크를 다 돌았으면 visited return
return visited, chk
chk = False
cnt = 0
arr = [
[0,0,1,1,0],
[0,0,0,1,1],
[1,1,1,1,1],
[0,0,0,0,0]
]
n = len(arr)
m = len(arr[0])
visited = [[False] * m for _ in range(n)]
for i in range(n):
for j in range (m):
visited, chk = chunk(i, j, arr, visited)
if chk:
cnt +=1
print(cnt)
코테 TIP
👉
arr(mxn) 행렬에서
행렬 초기화 ( 내부 리스트에서 ⇒ 외부 괄호 순 )
n = len(arr) m = len(arr[0])
행렬 초기화 ( 내부 리스트에서 ⇒ 외부 괄호 순 )
visited = [[False] * m for _ in range(n)]
잘못 접근했던 부분들
- 연산자 우선 순위 문제 (‘|’ 와 ‘or’)
👉
if (0 > (x+dx) | (x+dx) > n-1) | (0 > (y+dy) | (y+dy) > m-1):
⇒ 비트 연산자 |, &, ^는 우선순위가 높아 (0 > ( (x+dx) | (x+dx) )) > n-1 이 꼴로 연산해버림
if (0 > (x+dx) or (x+dx) > n-1) or (0 > (y+dy) or (y+dy) > m-1):
⇒ 비트 연산자 |, &, ^는 우선순위가 높아 (0 > ( (x+dx) | (x+dx) )) > n-1 이 꼴로 연산해버림
if (0 > (x+dx) or (x+dx) > n-1) or (0 > (y+dy) or (y+dy) > m-1):
⇒ python 코테에서 연산자는 반드시 “OR”, “AND”, “NOT”으로!!!
- 스택 카운팅 (chk의 위치)👉실수 : pop이후 먼저 1이면 stack에서 방문 처리하고 넘기기 방식
pythonif (arr[x][y]) == 1 : visited[x][y] = True continue chk = True visited[x][y] = True
⇒ 결국 1이 아닌 모든 0의 위치에서 카운팅 = 기본적으로 탐색 알고리즘에서 방문했더라도, 시작점 데이터는 스택에 들어감 = 오류
👉쉽게 해결 : 스택 들어가기도 전에 그냥 밖에서 처리 하고 스택에는 시작점이 0인값만!python# 출발점이 1이거나 방문했던 곳이면 그냥 chk는 false로 넘기기 if arr[x][y] == 1 or visited[x][y]: return visited, False
⇒ visited에 1인 값은 false로 바뀌지 않음!