며칠 동안 고민 고민하고 많은 '틀렸습니다'와 '시간 초과'를 만났다..
아직도 파이썬으로는 시간 초과가 나오지만... 파이썬으로 시간 초과 안 나오는 로직은 나중에 생각하기로 하고.. pypy로는 통과했다 !!
아이디어 ⭐
check 함수 -> 빙산이 두 부분 이상으로 나뉘었는지 체크
melt 함수 -> 1년마다 빙산의 각 구역을 물과 닿은 부분만큼 녹임(0까지만 녹임)
all_melt 함수 -> 모든 빙산이 녹았는지 체크하는 함수
year = 0으로 초기화하고 시작
계속 빙산이 두 덩어리로 나뉘었는지 체크함.
1) 두 덩어리로 나뉘었으면 year을 출력하고 break
2) 두 덩어리로 나뉘지 않았으면
1-1) 빙산이 다 녹았으면(두 덩어리로 나뉘는 게 불가능한 것이니까) 0을 출력하고 break
1-2) 빙산이 다 녹지 않았으면 1년 더 (year에 1을 추가하고, melt())
코드 👩💻
(완성 코드가 아닙니다.)
from collections import deque
import sys
input = sys.stdin.readline
N, M = map(int, input().split())
sea = []
for _ in range(N):
sea.append(list(map(int, input().split())))
# 상우하좌
di = [-1, 0, 1, 0]
dj = [0, 1, 0, -1]
# 두 부분 이상으로 나뉘어졌는지 체크
def check():
dq = deque()
ch = list([0] * M for _ in range(N))
ices_cnt = 0
for i in range(1, N - 1):
for j in range(1, M - 1):
if ch[i][j] == 0 and sea[i][j] != 0:
dq.append((i, j))
ch[i][j] = 1
ices_cnt += 1
while dq:
i, j = dq.popleft()
for mode in range(4):
ii = i + di[mode]
jj = j + dj[mode]
if 1 <= ii < N - 1 and 1 <= jj < M - 1 and ch[ii][jj] == 0 and sea[ii][jj] != 0:
ch[ii][jj] = 1
dq.append((ii, jj))
if ices_cnt <= 1:
return False
return True
# 1년마다 녹이기
def melt():
melts = list([0] * M for _ in range(N)) # 빙산 얼마나 녹아야 하는지 저장하는 리스트
for i in range(1, N - 1):
for j in range(1, M - 1):
if sea[i][j] != 0:
# 얼마나 빙산 줄어들지
melting_spots = 0
for mode in range(4):
ii = i + di[mode]
jj = j + dj[mode]
if 0 <= ii < N and 0 <= jj < M and sea[ii][jj] == 0:
melting_spots += 1
melts[i][j] = melting_spots
# 그만큼씩 빼주기
for i in range(1, N - 1):
for j in range(1, M - 1):
if sea[i][j] != 0:
for _ in range(melts[i][j]):
if sea[i][j] > 0:
sea[i][j] -= 1
# 다 녹았는지 체크하는 함수
def all_melt(): # True or False를 리턴
for i in range(1, N - 1):
for j in range(1, M - 1):
if sea[i][j] != 0:
return False
return True
year = 0
while True:
if check(): # 빙산이 두 덩어리로 나눠졌으면
print(year)
break
else: # 빙산이 두 덩어리로 나눠지지 않았는데
if all_melt(): # 빙산이 다 녹았으면
print(0)
break
else: # 빙산이 다 안 녹았으면 1년 더 !
year += 1
melt()
고민과 깨달음. 반성 🤔
코드를 이렇게 짜고 틀려서, 계속 고민했다..
로직은 분명히 맞는 것 같고, 테스트 케이스나 문제 게시판의 반례들은 잘 통과하는데 왜 틀리지??
나는 정말 정말 모르겠어서, 친구에게 부탁했다. 친구도 로직이 맞는 것 같은데 왜 틀리지? 하면서 1시간 가까이 봐줬다.
그래서 찾은 오류....
변수의 스코프!! 때문이었다...
check() 함수의
i, j = dq.popleft()
for mode in range(4):
ii = i + di[mode]
jj = j + dj[mode]
이 부분이다.. for i , for j 안에 있는데 또 i, j 를 쓴 것이다.. 이 부분만 고치니 맞았다!! (그런데 왜 테스트 케이스는 잘 통과한 건지 모르겠다..)
문제 풀 때는 변수 이름을 그냥 막 썼다..
그러다 보니 이런 실수를 한 것 같다 ㅠㅠ 너무 자연스럽게 쓰던 변수들이라서, 어디에서 틀렸나 찾기도 힘들었다..
앞으로는 문제 풀 때도 변수 이름을 잘 쓰도록 노력해야겠다!
'즐거운 PS 👩💻🥰' 카테고리의 다른 글
[백준-파이썬] 2591: 숫자카드 (0) | 2021.10.08 |
---|---|
[백준-파이썬] 2156: 포도주 시식 (0) | 2021.10.08 |
[백준-파이썬] 2258: 정육점 (0) | 2021.10.08 |
[백준-파이썬] 22252: 정보 상인 호석 (0) | 2021.10.08 |
[백준-파이썬] 1463: 1로 만들기 (0) | 2021.10.08 |