Algorithm(BOJ, Python)/BFS&DFS

[백준_2573] 빙산 python

kurooru 2022. 8. 20. 11:12

첫째로 실패했던 것은,

is_divided()함수에서,

빙산이 있고, 방문한 적 없는 빙산을 체크해야 하는데,

두 번째 조건을 빼 놓고 생각했다는 것,

 

두 번째로 실패했던 것은,

최대 리커전 횟수를 늘려 주지 않았다는 것.

이외에는 재밌게 푼 문제같다.

# 입력

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

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

# 함수들

# is_ocean(x, y)
def is_ocean(x, y):
    return not north_pole[x][y]

# check_pow(x, y)
def check_pow(x, y):
    # pow
    pow = 0

    # dxs, dys
    dxs, dys = [-1, 1, 0, 0], [0, 0, 1, -1]
    for dx, dy in zip(dxs, dys):
        # 주변 위치
        nx, ny = x + dx, y + dy
        # 바다이면
        if is_ocean(nx, ny):
            # pow 올려주기
            pow += 1
    
    # pow 반환
    return pow

# simulate()
def simulate():
    
    global north_pole

    # 위치와 녹을 정도를 기록해 줄 리스트
    pos_and_pow = []

    # 북극 돌면서
    for i in range(n):
        for j in range(m):
            # 빙산을 만나면
            if north_pole[i][j]:
                # 좌표와 녹을 정도를 측정하여 리스트에 기록
                pos_and_pow.append((i, j, check_pow(i, j)))
    
    # 녹여주기
    for x, y, p in pos_and_pow:
        north_pole[x][y] -= p
    
    # 녹이고 나서 음수가 된 애들 0으로 돌려주기
    for i in range(n):
        for j in range(m):
            if north_pole[i][j] < 0:
                north_pole[i][j] = 0

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

# check(x, y)
def check(x, y):
    # 범위 내에 있고, 방문한 적 없고, 바다가 아니면 가능
    return in_range(x, y) and not visited[x][y] and north_pole[x][y]

# dfs(x, y)
def dfs(x, y):
    # dxs, dys
    dxs, dys = [-1, 1, 0, 0], [0, 0, -1, 1]
    for dx, dy in zip(dxs, dys):
        # 다음 위치
        nx, ny = x + dx, y + dy
        # 다음 위치가 갈 수 있으면,
        if check(nx, ny):
            # 방문 처리 해 주고,
            visited[nx][ny] = 1
            # dfs호출
            dfs(nx, ny)

# is_divided()
def is_divided():
    
    # area -> 이어져 있는 땅 개수
    area = 0
    
    # 북극을 돌면서
    for i in range(n):
        for j in range(m):
            # 빙산이 있고, 방문한 적 없는 빙산이면
            if north_pole[i][j] and not visited[i][j]:
                # area 개수 올려주고
                area += 1
                # 방문 처리 해주고
                visited[i][j] = 1
                # dfs 호출
                dfs(i, j)
    
    # area가 2 이상이면
    if area >= 2:
        # 나뉘어져 있음
        return True
    
    # 아니면 실패
    return False

# all_melted()
def all_melted():
    # 북극을 돌면서
    for i in range(n):
        for j in range(m):
            # 빙산을 발견하면
            if north_pole[i][j]:
                # 실패
                return False
    # 다 돌았는데 빙산이 없으면 성공
    return True

# 설계

# 최대 리커젼 횟수 올려주기
import sys
sys.setrecursionlimit(15000)

# ans
ans = 0
while True:

    # visited (매번 초기화)
    visited = [
        [0] * m
        for _ in range(n)
    ]

    # 만약 다 녹았는데 안나눠졌으면,
    if all_melted():
        # 0 출력 후
        print(0)
        # 반복문 종료
        break

    # 만약 두 개로 나뉘어졌으면
    elif is_divided():
        # 정답 출력해주고,
        print(ans)
        # 반복문 종료
        break

    # 아직 안나눠졌으면,
    else:
        # 시뮬레이션 돌려주고,
        simulate()
        # ans 하나 올려줌
        ans += 1