[백준] 2573 빙산 풀이 PythonOnlineJudge2021. 9. 14. 00:47
Table of Contents
반응형
이번 글에서는 문제에 대한 설명과 풀이보다 골드 난이도임에도 불구하고 무려 11WA를 받게된 이유, 그리고 드디어 Solved 할 수 있었던 이유를 찾고 포스팅 했습니다.
혹시 "맞는데 왜 틀려" 늪에 빠져있다면 이 글을 보았을 때 도움이 될 수 있습니다😀
과거의 흔적
틀렸던 이유
1. RecursionError
Python의 경우 재귀 함수의 깊이가 1000으로 고정되어 있습니다.
만약 1000번보다 더 큰 재귀를 돌기 위해선 Recursion을 설정해줘야 합니다.
5개월 전 당시엔 이를 DFS로 풀다가 놓쳤던 것 같네요
2. 시간초과 및 틀렸습니다
과거의 코드를 보니 빙산이 분리되는 구간에서 줄일 수 있는 로직이 보였고, 애초에 너무 복잡하게 생각을 했는지 코드가 직관적이지 못합니다 ㅠㅠ 그리고 빙산을 녹이고 즉각 반영하는 것이 아닌 후처리를 해야 하는데 이 부분을 놓쳤습니다.
3. 다시 풀었는데 3WA
녹은 빙하만큼 field에 후처리를 하고 한번에 반영해주는 로직을 선택했는데, 이 과정에서 field의 일부 값이 음수가 되어버리는 케이스를 목격했습니다. 음수가 되면 BFS를 할 때 물로 인식을 하지 않기 때문에(물은 0이므로) Wrong Answer을 받았습니다.
맞았던 이유
- 빙산이 갈라지면 해당 년(year)을 반환한다
- 빙산이 갈라지지 않는 경우엔 0을 반환한다.
- 애초에 빙산이 없다(모두 물이다)
- 필드에 빙산을 녹일 물이 없다? (이 경우는 테스트 케이스에 없으며 필드에 반드시 물이 존재합니다)
- 갈라지지 않고 모두 녹아버리는 경우
소스코드
Python3
from collections import deque
N,M = map(int,input().split())
field = []
iceblock = deque()
direction = [[0,1],[1,0],[-1,0],[0,-1]]
for i in range(N):
line = list(map(int,input().split()))
field.append(line)
for j in range(len(line)):
if line[j]!=0:
iceblock.append([j,i])
# 1. 빙산 분리 체크
def checkBreakIce():
visited = [[0]*M for _ in range(N)]
dq = deque()
cnt = 0
for ix,iy in iceblock:
if visited[iy][ix]==1:continue
cnt+=1
if cnt>=2:
return True #분리되면 True 반환
dq.append([ix,iy])
while dq:
x,y = dq.popleft()
for dx,dy in direction:
nx,ny = dx+x,dy+y
if 0>nx or 0>ny or M<=nx or N<=ny or field[ny][nx]==0:continue
if visited[ny][nx]==1:continue
visited[ny][nx]=1
dq.append([nx,ny])
return False
#2. 빙산의 녹음
def melting():
size = len(iceblock)
sumfield = [[0]*M for _ in range(N)]
for i in range(size):
x,y = iceblock.popleft()
water_cnt = 0
for dx,dy in direction:
nx,ny = x+dx, y+dy
if 0>nx or 0>ny or M<=nx or N<=ny or field[ny][nx]!=0:continue
water_cnt+=1
sumfield[y][x]-=water_cnt
if field[y][x]-water_cnt>0:#아직 빙산이 덜녹았다면
iceblock.append([x,y]) #다시 빙산 리스트에 추가
for i in range(N):
for j in range(M):
if field[i][j] + sumfield[i][j] < 0:
field[i][j]=0
else:
field[i][j] += sumfield[i][j]
def solution():
year = 1
while True:
melting()
if not iceblock:#빙산이 이미 모두 녹았거나 갈라졌다면
return 0
if checkBreakIce():
return year
year+=1
return 0
print(solution())
덱(deque)을 쓴 이유
남아있는 빙하를 체크하기 위해 list를 사용했습니다. 이 과정에서 left remove와 right append가 빈번히 일어나기 때문에 deque를 사용했습니다.
반응형
'OnlineJudge' 카테고리의 다른 글
[백준] 15684 사다리 조작 풀이 Python, Java (0) | 2021.09.22 |
---|---|
[백준] 2143 두 배열의 합 풀이 Python (0) | 2021.09.19 |
백준 1016 제곱ㄴㄴ수 풀이 Python (2) | 2021.06.24 |
[Codility] Lesson4 MaxCounters 풀이 Python (0) | 2021.06.22 |
[Codility] Lesson4 MissingInteger 풀이 Python (0) | 2021.06.22 |
@CODe_ :: 강승현입니다
인프런 지식공유자로 활동하고 있으며 MSA 전환이 취미입니다. 개발과 관련된 다양한 정보를 몰입감있게 전달합니다.