Algorithm(BOJ, Python)/BFS&DFS

[백준_2583] 영역 구하기 python

kurooru 2022. 8. 30. 18:23

dfs 문제를 풀때마다 느끼는거지만,

파이썬의 최대 리커전가능 횟수 디폴트값이 1000인건,

너무 야박한 것 같다.

 

꼭지점 좌표로 입력 받을 때,

역으로 이를 생각해야 하기에 조금 불편하겠다 싶었는데,

곰곰히 생각해보니 점대칭으로 그냥 받아도 아무차이없을 것 같아,

그대로 해봤더니 성공했다.

 

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

# grid
grid = [
    [0] * m
    for _ in range(n)
]

# 꼭지점 좌표 입력
for _ in range(k):
    sy, sx, ey, ex = map(int, input().split())
    # 직사각형 그려주기
    for i in range(sx, ex):
        for j in range(sy, ey):
            grid[i][j] = 1

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

# is_connected(x, y)
def is_connected(x, y):
    # 범위 내에 있고, 직사각형 아니고, 방문한 적 없으면 가능
    return in_range(x, y) and not grid[x][y] and not visited[x][y]

# dfs(x, y)
def dfs(x, y):

    global curr_area

    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_connected(nx, ny):
            # 현재 영역 크기 하나 올려주고
            curr_area += 1
            # 방문 처리 해 주고
            visited[nx][ny] = 1
            # dfs 호출
            dfs(nx, ny)

# 설계
# visited
visited = [
    [0] * m
    for _ in range(n)
]

# 영역 갯수
area_num = 0

# dfs결과 영역의 크기 담아 줄 배열
area_list = []

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

# grid 돌면서
for i in range(n):
    for j in range(m):
        # 비어있고, 방문한 적 없는 칸을 만나면,
        if not grid[i][j] and not visited[i][j]:
            # 현재 영역의 크기
            curr_area = 1
            # 영역 갯수 올려주고
            area_num += 1
            # 방문 처리 해 주고,
            visited[i][j] = 1
            # dfs 돌려주고,
            dfs(i, j)
            # 영역 크기 추가
            area_list.append(curr_area)

# area_list 정렬
area_list.sort()

# 출력
print(area_num)
for area in area_list:
    print(area, end=' ')