백준 2468번 안전 영역 (Python, BFS, 브루트포스, Silver1)

전승재·2023년 8월 28일
0

알고리즘

목록 보기
31/88

백준 2468번 안전 영역 문제 바로가기

문제 이해

문제

재난방재청에서는 많은 비가 내리는 장마철에 대비해서 다음과 같은 일을 계획하고 있다. 먼저 어떤 지역의 높이 정보를 파악한다. 그 다음에 그 지역에 많은 비가 내렸을 때 물에 잠기지 않는 안전한 영역이 최대로 몇 개가 만들어 지는 지를 조사하려고 한다. 이때, 문제를 간단하게 하기 위하여, 장마철에 내리는 비의 양에 따라 일정한 높이 이하의 모든 지점은 물에 잠긴다고 가정한다.

어떤 지역의 높이 정보는 행과 열의 크기가 각각 N인 2차원 배열 형태로 주어지며 배열의 각 원소는 해당 지점의 높이를 표시하는 자연수이다.

위의 사진에서는 비가 4만큼 와서 높이가 4이하인 지역은 잠긴다.
안잠긴 안전한 영역은 총 5개이다.

이와 같이 장마철에 내리는 비의 양에 따라서 물에 잠기지 않는 안전한 영역의 개수는 다르게 된다. 위의 예와 같은 지역에서 내리는 비의 양에 따른 모든 경우를 다 조사해 보면 물에 잠기지 않는 안전한 영역의 개수 중에서 최대인 경우는 5임을 알 수 있다.

어떤 지역의 높이 정보가 주어졌을 때, 장마철에 물에 잠기지 않는 안전한 영역의 최대 개수를 계산하는 프로그램을 작성하시오.

입력

첫째 줄에는 어떤 지역을 나타내는 2차원 배열의 행과 열의 개수를 나타내는 수 N이 입력된다. N은 2 이상 100 이하의 정수이다. 둘째 줄부터 N개의 각 줄에는 2차원 배열의 첫 번째 행부터 N번째 행까지 순서대로 한 행씩 높이 정보가 입력된다. 각 줄에는 각 행의 첫 번째 열부터 N번째 열까지 N개의 높이 정보를 나타내는 자연수가 빈 칸을 사이에 두고 입력된다. 높이는 1이상 100 이하의 정수이다.

출력

첫째 줄에 장마철에 물에 잠기지 않는 안전한 영역의 최대 개수를 출력한다.

문제 접근

문제에 들어가기 앞서서 3가지 단계로 나누고 시작했다.

  • 물의 양 조절하기
  • 물에 잠기는 영역 확인하기
  • 안전한영역의 개수 체크하기

반복문으로 비의 양을 높이의 최대값까지 조절하면서 확인하도록 구현해야겠다고 생각했고, 물에 잠기는 영역을 확인하기 위한 2차원 배열을 생성해야겠다고 생각했다.
또한 안전한 영역의 개수 체크를 위해서 BFS를 사용하여 체크한 영역을 중복으로 체크하는 일이 없도록 해주어야 한다고 생각하고 문제를 풀기 시작했다.

문제 풀이

물의 양 조절하기

물의 양을 조절하기위해서 범위를 정해야하는데 지역에서 가장 높은 지역의 높이를 max_rain에 저장하고 rain을 0부터 max_rain-1까지 반복했다.

max_rain = max(map(max, graph))
for rain in range(max_rain): # 물의 양 조절

물에 잠기는 영역 확인하기

물에 잠기려면 rain보다 낮은 지역이어야 한다. 잠기는 지역인지를 나타내는 sink 2차원 배열을 선언하고 만약 rain보다 높이가 낮다면 sink[i][j]=True를 통해 잠겼음을 나타내주었다.

for rain in range(max_rain): # 물의 양 조절
    count = 0 # 안전한 영역의 개수 카운트
    sink = [[False for _ in range(N)] for i in range(N)] # 물에 잠긴 부분 초기화
    for i in range(N):
        for j in range(N):
            if graph[i][j]<=rain:
                sink[i][j]=True # 물에 잠기는 영역 확인하기

안전한 영역의 개수 체크하기

bfs를 안잠긴 지역의 좌표 i,j를 파라미터로 넣어서 실행해준다.
잠기지 않은 지역이 있기에 count+1을 해주고 그 지역 역시 잠겼다고 가정해준다. (visited와 같은 원리)
그리고 상하좌우를 확인하면서 잠기지 않은 지역이 있다면 그 지역도 잠겼다고(방문하였다고) 가정한다.

결국 가장 처음에 안잠긴 지역의 좌표 i,j와 연결된 잠기지 않은 지역이 모두 잠겼다고 표시가 되고 count는 1만 증가한다.

이렇게 모든 지역을 확인한 후에 count를 count_list에 추가한다.

출력으로는 count_list에서 가장 큰 값을 출력하면 된다.

dx = [0,0,-1,1]
dy = [1,-1,0,0]

def bfs(i,j):
    global count
    q = deque()
    q.append((i,j))
    sink[i][j] = True
    count += 1 # 안전한 영역 개수 1 추가
    while q:
        x,y = q.popleft()
        for i in range(4):
            nx = x + dx[i] # 상하좌우 확인
            ny = y + dy[i]
            if nx<0 or ny < 0 or nx >= N or ny >= N: # 영역 밖으로 나가면 x
                continue
            if sink[nx][ny]==False: # 상하좌우중 잠겨있지 않은 부분이 있다면
                sink[nx][ny] = True # 잠겼다고 가정시킴
                q.append((nx,ny))

제출 코드

import sys
from collections import deque
N = int(sys.stdin.readline())
graph = [list(map(int, sys.stdin.readline().split())) for _ in range(N)]
max_rain = max(map(max, graph))
# 물의 양 조절하기
# 물에 잠기는 영역 확인하기
# 안전한영역의 개수 체크하기
dx = [0,0,-1,1]
dy = [1,-1,0,0]
def bfs(i,j):
    global count
    q = deque()
    q.append((i,j))
    sink[i][j] = True
    count += 1 # 안전한 영역 개수 1 추가
    while q:
        x,y = q.popleft()
        for i in range(4):
            nx = x + dx[i] # 상하좌우 확인
            ny = y + dy[i]
            if nx<0 or ny < 0 or nx >= N or ny >= N: # 영역 밖으로 나가면 x
                continue
            if sink[nx][ny]==False: # 상하좌우중 잠겨있지 않은 부분이 있다면
                sink[nx][ny] = True # 잠겼다고 가정시킴
                q.append((nx,ny))
count_list = []
for rain in range(max_rain): # 물의 양 조절
    count = 0 # 안전한 영역의 개수 카운트
    sink = [[False for _ in range(N)] for i in range(N)] # 물에 잠긴 부분 초기화
    for i in range(N):
        for j in range(N):
            if graph[i][j]<=rain:
                sink[i][j]=True # 물에 잠기는 영역 확인하기
    for i in range(N):
        for j in range(N):
            if sink[i][j]==False: # 잠기지 않은 영역일 경우에만
                bfs(i,j) # bfs실행하여 영역모두 잠겼다고 가정하면서 안전한 영역 1 추가시키기
    count_list.append(count) # count_list에 추가 

print(max(count_list)) # count_list중에서 최대값을 출력

0개의 댓글