7576 토마토 문제 풀이

Rookedsysc·2024년 2월 13일
0
post-thumbnail

이 글을 쓰는 이유?

반례 찾기가 너무 힘들었던 문제였던 것 같다.
이 링크에서 나오는 반례를 모두 충족하지 못하면 문제가 틀렸다고 나온다.

문제 링크

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

문제 설명은 위에 들어가서 읽는게 더 정확할테니 따로 기술하지 않겠다.

내 첫 풀이

위상정렬에서 사용하던 indegree를 가져와서 아직 익지 않은 토마토를 Tracking해서 풀어주는 방식을 사용했다. 근데 이 코드를 사용하면 1%에서 무조건 실패가 났다. 반례란 반례는 다 찾아보고 테스트 코드도 다 확인했지만 이상한 점은 없었다.

근데 단톡방에서 어떤분이 '모든 토마토가 익는걸 확인하셧나요?'

라고 질문하시기에 graph의 값이 다 1로 변하는지 확인하던 중

    30 19
    0 -1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 -1
    -1 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 -1 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 -1
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 -1 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0

이 테스트 케이스의 답은 나오지만 모든 graph에 1이 표시되지 않고 듬성듬성 0이 보이는 것을 확인했다. 조금 머리를 굴려보니 답이 나왔다.
r : 1, c : 11 도 indegree['111']로 저장이 되고 r : 11, c : 1 도 indegree['111']로 저장이 되어서 발생하는 문제다.
저 테스트 케이스에서 어떤 실패가 나는지는 모르겠지만 이것과 연관되있음이 분명해 보였다. 그래야만 한다.

from collections import deque

C, R = map(int, input().split())
graph = []
for _ in range(R):
  graph.append(list(map(int, input().split())))

# 안익은 토마토
indegree = {}
start_q = deque()

for r in range(R) :
  for c in range(C) :
    if graph[r][c] == 0 :
      indegree[f"{r}{c}"] = True
    elif graph[r][c] == 1 :
      start_q.append([r,c])
_d = [[1,0],[-1,0],[0,1],[0,-1]]
indegree_cnt = len(indegree.keys())
if len(graph) <= 0 :
  print(-1)
elif indegree_cnt <= 0 :
  print(0)
else :
  cnt = 0
  while True :
    cnt += 1
    next_q = deque()
    for q in start_q :
      r, c = q
      for d in _d :
        nr, nc = r + d[0], c + d[1]
        if -1 < nr < R and -1 < nc < C :
          if f'{nr}{nc}' in indegree :
            next_q.append([nr,nc])
            indegree_cnt -= 1
            graph[nr][nc] = 1
            del indegree[f'{nr}{nc}']
    # 모든 토마토가 다 익은 경우
    if indegree_cnt == 0 :
      print(cnt)
      break
    elif len(next_q) > 0 :
      start_q = next_q
    # 모든 q를 다 순회했지만 아직 안익은 토마토가 남은 경우
    else :
      print(-1)
      break

내 두 번째 풀이

그냥 f'{r}{c}'와 같은 형식으로 들어가는 모든 라인에 f'{r}-{c}' 처럼 구분자를 넣어서 해결해줬다.

from collections import deque

C, R = map(int, input().split())
graph = []
for _ in range(R):
  graph.append(list(map(int, input().split())))

# 안익은 토마토
indegree = {}
start_q = deque()

for r in range(R) :
  for c in range(C) :
    if graph[r][c] == 0 :
      indegree[f"{r}-{c}"] = True
    elif graph[r][c] == 1 :
      start_q.append([r,c])
_d = [[1,0],[-1,0],[0,1],[0,-1]]
indegree_cnt = len(indegree.keys())
if len(graph) <= 0 :
  print(-1)
elif indegree_cnt <= 0 :
  print(0)
else :
  cnt = 0
  while True :
    cnt += 1
    next_q = deque()
    for q in start_q :
      r, c = q
      for d in _d :
        nr, nc = r + d[0], c + d[1]
        if -1 < nr < R and -1 < nc < C :
          if f'{nr}-{nc}' in indegree :
            next_q.append([nr,nc])
            indegree_cnt -= 1
            graph[nr][nc] = 1
            del indegree[f'{nr}-{nc}']
    # 모든 토마토가 다 익은 경우
    if indegree_cnt == 0 :
      print(cnt)
      break
    elif len(next_q) > 0 :
      start_q = next_q
    # 모든 q를 다 순회했지만 아직 안익은 토마토가 남은 경우
    else :
      print(-1)
      break

좀 더 효율적인 풀이?🤔

너무 파이써닉하게 풀이된 풀이를 안좋아하는데 이 블로그의 풀이가 깔끔해보여서 가져왔다.
내가 한 풀이보다 약 3배 정도 빠르다.

👇 위가 내 풀이 아래가 저 블로그에서 나온 풀이

from collections import deque
import sys
input = sys.stdin.readline

m, n = map(int, input().split()) # 가로, 세로
graph = []
for _ in range(n):
    graph.append(list(map(int, input().split())))

# 익은 토마토의 위치 queue에 추가
queue = deque()
for i in range(n):
    for j in range(m):
        if graph[i][j] == 1:
            queue.append([i, j])

# BFS 함수 정의
def bfs():
    while queue:
        x, y = queue.popleft()
        dx = [-1, 1, 0, 0]
        dy = [0, 0, -1, 1]
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            # 상하좌우에 익지 않은 토마토(0)가 있으면 1을 더해 몇 번째인지 세주고
            if 0 <= nx < n and 0 <= ny < m and graph[nx][ny] == 0:
                graph[nx][ny] = graph[x][y] + 1
                queue.append((nx, ny)) # 큐에 새로운 토마토 위치 추가

# BFS; 토마토 익히기 시작
bfs()

# bfs 종료 후
day = 0
for row in graph:
    for i in row:
        if i == 0:  # 익지 않은 토마토가 있으면(=토마토가 모두 익지 못하는 상황) -1 출력
            print(-1)
            exit() # 다음 행의 여부와 관계 없이 -1만 출력해야하므로 종료시킴
    else: # 그래프에서 가장 큰 값이 마지막으로 익은 토마토임 → 한 줄씩 최댓값을 day로 갱신하며 최댓값 찾기
        day = max(day, max(row)) 

# 처음 시작을 0이 아닌 1부터 했으므로 -1을 해야 날짜를 구할 수 있음 
print(day-1)

0개의 댓글