물을 채울 수 있는 조건은 다음과 같다.
현재 높이를 A라 할 때
- 높이 A와 이어지는 영역은 테두리에 닿으면 안 된다. (물이 땅으로 흐름)
- 상하좌우의 높이가 A보다 작으면 안 된다. (작은 쪽 높이가 테두리로 이어짐)
한번 채워진 영역은 다시 한번 더 채워질 수 있기에 (예제 2번 기준) 높이가 낮은 곳부터 탐색을 해야 한다고 생각했다.
코드의 흐름은 다음과 같다.
- 찾을 높이를 1 ~ 9까지 정하고 이 높이를 wall이라 한다. (main 함수)
- wall 값과 동일한 값을 가진 가진 좌표들을 구한다. (findWall 함수)
- 만약 테두리와 이어지면 무효
- 상하좌우로 탐색한 높이의 최솟값이 wall보다 낮으면 무효
- wall 보다 큰 값이 없다면, 해당 영역에 물을 채울 수 없으니 무효
- 영역을 구하면 상하좌우로 탐색한 높이 중 최솟값으로 갱신한다. (fillWater 함수)
from collections import deque
import sys
input = lambda: sys.stdin.readline().strip('\n')
R, C = map(int, input().split())
board = [[] for _ in range(R)]
for i in range(R):
S = input()
for s in S:
board[i].append(ord(s) - ord('0'))
dir = [[1, 0], [-1, 0], [0, 1], [0, -1]]
def main():
ans = 0
for i in range(1, 10):
ans += findWall(i)
print(ans)
# 테두리는 탐색 X
def findWall(wall):
ret = 0
visit = [[False] * C for _ in range(R)]
for r in range(R):
if r == 0 or r == R - 1:
continue
for c in range(C):
if c == 0 or c == C - 1:
continue
if visit[r][c]:
continue
if board[r][c] == wall:
visit[r][c] = True
route, minWall = getArea(wall, visit, r, c)
ret += fillWater(route, minWall, wall)
return ret
def getArea(wall, visit, hereR, hereC):
route = [(hereR, hereC)]
minWall = float("inf")
error = False
q = deque([(hereR, hereC)])
while q:
hereR, hereC = q.popleft()
for d in dir:
thereR, thereC = hereR + d[0], hereC + d[1]
if thereR < 0 or thereR >= R or thereC < 0 or thereC >= C:
continue
there = board[thereR][thereC]
# 현재 벽과 다른 높이의 벽을 만나면 최솟값 갱신
if there != wall:
minWall = min(minWall, there)
continue
if visit[thereR][thereC]:
continue
# 만약 현재 높이가 테두리를 포함한다면 물을 채울 수 없음
if thereR == 0 or thereR == R - 1 or thereC == 0 or thereC == C - 1:
error = True
visit[thereR][thereC] = True
route.append((thereR, thereC))
q.append((thereR, thereC))
# 현재 높이의 벽이 가장 크거나 가장 낮은 벽이 현재 높이의 벽보다 작거나 테두리를 포함하면 무효
if minWall == float("inf") or minWall < wall or error:
return [], 0
return route, minWall
def fillWater(route, minWall, wall):
ret = len(route) * (minWall - wall)
for r, c in route:
board[r][c] = minWall
return ret
if __name__ == '__main__':
main()
'알고리즘 > 백준' 카테고리의 다른 글
백준[1981] 배열에서 이동 (Python3) (0) | 2023.02.11 |
---|---|
백준[1863] 스카이라인 (Python3) (0) | 2023.02.03 |
백준[1561] 놀이 기구 (Python3) (0) | 2023.01.30 |
백준[23327] 리그전 오브 레전드 (Python3) (0) | 2023.01.30 |
백준[17136] 색종이 붙이기 (Python3) (0) | 2023.01.27 |