0. 문제 링크
https://www.acmicpc.net/problem/2573
2573번: 빙산
첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을
www.acmicpc.net
1. 풀이 방법
우선 빙산의 녹음을 구현한 함수인 melt()
와 그룹화하는 함수인 group()
함수를 구현했다.
그리고 빙산 근처에 바다의 개수를 세는 adj
도 따로 만들어서, 빙산 근처에 몇 개의 바다가 있는지 셌다.
melt()
함수를 사용하고, 다시 인접한 바다의 개수를 셌다.
만약 특정 빙산이 모두 녹았다면 해당 빙산은 adj
딕셔너리에서 pop
하였다.
group()
함수에서는 BFS
를 사용했고, 모두 한 그룹이 되지 않으면 같은 과정을 반복하였다.
이때 한 그룹이 되는 건 어떻게 알았냐면, 그냥 아무 좌표 하나 잡고 BFS
를 하면서 set
에 넣는다.
이후 BFS
가 끝나고, set
과 adj
의 길이를 비교했을 때, 같다면 빙산이 하나의 그룹으로 이루어진 것이다.
만약 길이가 다르다면 이는 필연적으로 빙산이 두 개 이상의 그룹으로 나뉜 것이므로 그대로 반환하였다.
2. 코드
import sys
from collections import deque
def melt():
# 빙산의 녹음을 구현한 함수
adj_list = list(adj.items())
for (y, x), cnt in adj_list:
maps[y][x] = max(maps[y][x] - cnt, 0)
if maps[y][x] == 0:
adj.pop((y, x)) # 만약 모두 녹았다면 이제 인접한 바다가 있는지 체크할 필요가 없음
for (y, x) in adj.keys():
adj[(y, x)] = 0
for dy, dx in dir:
ny, nx = y + dy, x + dx
if 0 <= ny < n and 0 <= nx < m:
if maps[ny][nx] == 0:
adj[(y, x)] += 1 # 다시 인접한 바다의 개수를 셈
def group():
if len(adj) == 0: # 만약 모두 녹기 전까지 분리된 적이 없다면 -1를 반환함
return -1
dq.append(list(adj.keys())[0]) # 맨 처음 좌표를 넣음
check = set()
while dq:
y, x = dq.popleft()
for dy, dx in dir:
ny, nx = y + dy, x + dx
if 0 <= ny < n and 0 <= nx < m and (ny, nx) not in check:
if maps[ny][nx]:
dq.append((ny, nx))
check.add((ny, nx))
if len(check) != len(adj): # 두 개의 개수가 다르면 2덩이 이상으로 나뉘어진 것이므로 그대로 반환함
return True
return False
def sol():
cnt = 1
while True:
melt()
match group():
case True:
return cnt
case False:
cnt += 1
case -1:
return 0
if __name__ == "__main__":
input = sys.stdin.readline
n, m = map(int, input().split())
maps = [[m for m in map(int, input().split())] for _ in range(n)]
adj = dict()
dq = deque()
dir = [[-1, 0], [0, 1], [1, 0], [0, -1]]
for y in range(n):
for x in range(m):
if maps[y][x]:
adj[(y, x)] = 0
for dy, dx in dir:
ny, nx = y + dy, x + dx
if 0 <= ny < n and 0 <= nx < m:
if maps[ny][nx] == 0:
adj[(y, x)] += 1 # 인접한 바다의 개수를 셈
print(sol())
3. 마무리
'Computer Science > 알고리즘' 카테고리의 다른 글
[백준 - Python] 2668 - 숫자 고르기 (0) | 2023.03.08 |
---|---|
[백준 - Python] 7569 - 토마토 (0) | 2023.03.08 |
[백준 - Python] 19236 - 청소년 상어 (2) | 2023.03.08 |
[백준 - Python] 20061 - 모노미노도미노 2 (0) | 2023.03.08 |
[백준 - Python] 2580 - 스도쿠 (0) | 2023.03.08 |