알고리즘/BOJ

[ 백준 / 파이썬 ] 2583. 영역 구하기

감싹이 2023. 4. 4. 08:00

https://www.acmicpc.net/problem/2583

 

2583번: 영역 구하기

첫째 줄에 M과 N, 그리고 K가 빈칸을 사이에 두고 차례로 주어진다. M, N, K는 모두 100 이하의 자연수이다. 둘째 줄부터 K개의 줄에는 한 줄에 하나씩 직사각형의 왼쪽 아래 꼭짓점의 x, y좌표값과 오

www.acmicpc.net

🎉🎉 문제

눈금의 간격이 1인 M×N(M,N≤100)크기의 모눈종이가 있다. 이 모눈종이 위에 눈금에 맞추어 K개의 직사각형을 그릴 때, 이들 K개의 직사각형의 내부를 제외한 나머지 부분이 몇 개의 분리된 영역으로 나누어진다.

M, N과 K 그리고 K개의 직사각형의 좌표가 주어질 때, K개의 직사각형 내부를 제외한 나머지 부분이 몇 개의 분리된 영역으로 나누어지는지, 그리고 분리된 각 영역의 넓이가 얼마인지를 구하여 이를 출력하는 프로그램을 작성하시오.

 

 

🎉🎉 풀이

✅ 직사각형이 어디에 있는지 표시된 2차원 배열을 만든다

✅ 2차원 배열을 돌면서 빈 공간을 dfs로 탐색해 넓이와 영역의 개수를 구한다

✅ 출력할 때 *sorted(list) 하면 리스트 원소들을 공백을 두고 출력해주는 듯

 

 

🎉🎉 코드

import sys
sys.setrecursionlimit(10**6)

def dfs(i, j, n, m):
  global cnt
  visited[i][j] = True
  cnt += 1 #넓이 1칸 추가

  #상우하좌
  di = [-1, 0, 1, 0]
  dj = [0, 1, 0, -1]

  for k in range(4):
    ni = i+di[k]
    nj = j+dj[k]

    if 0<=ni<n and 0<=nj<m:
      if not visited[ni][nj] and graph[ni][nj] == 0: #아직 방문 안 한 곳이면서 비어있는 영역이면
        dfs(ni, nj, n, m) #탐색하러 들어간다

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

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

for _ in range(k):
  x1, y1, x2, y2 = map(int, input().split()) #직사각형 왼쪽 아래 모서리와 오른쪽 위 모서리의 좌표
  for i in range(y1, y2):
    for j in range(x1, x2):
      graph[i][j] = 1 #직사각형 표시


visited = [[False]*m for _ in range(n)] #방문처리

answer = [] #넓이 담을 배열
ground = 0 #영역의 개수
global cnt
for i in range(n):
  for j in range(m):
    cnt = 0
    if not visited[i][j] and graph[i][j] == 0:
      dfs(i, j, n, m)
      answer.append(cnt) #카운트 한 넓이를 기록
      ground += 1 #영역의 개수 추가


print(ground)
print(*sorted(answer)) #오름차순 정렬해서 출력