백준 2583번 - 영역 구하기
영역 구하기 문제 바로 가기
풀이 날짜: 2026-01-17
baekjoon 알고리즘 문제 풀이
풀이 코드
import sys
input = sys.stdin.readline
from collections import deque
rects = []
n,m,k = map(int, input().split())
for _ in range(k):
x1,y1,x2,y2 = map(int, input().split())
rects.append((x1,y1,x2,y2))
dx = [0,0,-1,1]
dy = [-1,1,0,0]
answer = []
graph = [[0] * m for _ in range(n)]
for x1,y1,x2,y2 in rects:
for y in range(y1,y2):
for x in range(x1,x2):
i = n-1-y
j = x
graph[i][j] = 1
visited = [[False] * m for _ in range(n)]
def bfs(sx,sy):
q = deque([(sx,sy)])
visited[sx][sy] = True
count = 1
while q:
x,y = q.popleft()
for d in range(4):
nx = dx[d]+x
ny = dy[d]+y
if 0<=nx<n and 0<=ny<m and not visited[nx][ny] and graph[nx][ny] == 0:
visited[nx][ny] = True
q.append((nx,ny))
count+=1
return count
for i in range(n):
for j in range(m):
if graph[i][j] == 0 and not visited[i][j]:
answer.append(bfs(i,j))
answer.sort()
print(len(answer))
print(*answer)
문제 접근
이동할 수 없는 칸을 먼저 표시한 뒤, 남은 칸의 연결된 덩어리를 찾는 문제이다. 즉 전형적인 영역 구하기 문제였다. 따라서 바로 BRS/DFS로 돌리는 것이 아니라 사각형을 먼저 graph에 칠하는 것이 먼저였다.
좌표계 정의하기
문제에서 주어지는 좌표는 (0,0)이 왼쪽 아래이고 y가 위로 증가하지만, 파이썬의 2차원 배열은 (0,0)이 왼쪽 위이며 행 인덱스가 아래로 증가한다. 이 차이 때문에 사각형을 그대로 graph에 찍으면 상하가 뒤집혀 버린다. 이를 해결하기 위해 문제 좌표의 y값을 배열 인덱스로 바꿀 때 i = n - 1 - y라는 변환이 필요하다는 점을 이해하는 데 시간이 걸렸다.
사각형을 graph에 “칠하는” 단계
사각형 정보 (x1, y1, x2, y2)는 단순한 점 정보가 아니라, x는 x1부터 x2-1, y는 y1부터 y2-1까지의 모든 칸을 막아야 한다는 의미다. 이후에는 graph[i][j] = 1 을 사용해서 사각형 영역을 미리 막아뒀고, 이후 BFS에서는 값이 0인 칸만 이동하도록 했다.
헷갈렸던 점 정리
visited 배열을 분리해서 사용한 이유
graph에는 “막힌 칸(1)”과 “빈 칸(0)”의 정보만 저장하고, 방문 여부는 visited 배열로 따로 관리했다. 이렇게 분리하면 코드의 의미가 명확해지고, 같은 graph를 다른 조건으로 다시 탐색할 때도 유연하게 사용할 수 있다. 특히 영역 문제에서는 visited 체크를 좌표 단위로 정확히 하는 것이 중요하며, not visited[nx][ny] 형태로 써야 한다는 점을 실수하면서 확실히 배웠다.