5558. チーズ (Cheese)#

관찰#

문제는 주어진 격자 그래프에서
시작 지점 \( S \)에서 시작해서 1부터 \( N \)까지 순서대로 방문할 때,
최소 이동 비용을 구하는 것이다.

각 치즈는 순서대로 먹어야 하므로,
현재 위치에서 다음 목표 치즈까지의 최단 거리를 반복해서 구하는 문제로 환원할 수 있다.

격자는 가중치가 없는 그래프이기 때문에,
각 구간의 최단 거리는 BFS로 구하는 것이 가장 직관적이라 판단했고,
이를 기반으로 풀이를 구성했다.



시간 복잡도#

문제의 조건은
\( 1 \le H \le 1{,}000 \), \( 1 \le W \le 1{,}000 \), \( 1 \le N \le 9 \) 이다.

격자 전체에 대해 BFS를 한 번 수행하는데
\( O(H \cdot W) \) 의 시간이 걸리고,

N번의 BFS를 수행하면 총 \( O(N \cdot H \cdot W) \)의 시간복잡도가 발생한다.

최대값을 대입하면 \( 1000 \cdot 1000 \cdot 9 \approx 9{,}000{,}000 \) 으로,
1초 제한 내에 충분히 풀이가 가능하다.



최적화#

초기 코드 구성은
BFS함수 내에서 재귀적으로 1부터 \( N \)까지 탐색하는 코드를 구성했다.

하지만 이 경우

  • \( 1{,}000 \cdot 1{,}000 \) 크기의 visit 배열을 만드는 오버헤드
  • 재귀 구조 상 visit중복 생성 및 이전 배열 메모리를 해제하지 않음

으로 인해, 불필요한 메모리 할당 비용과 초기화 비용이 발생했다.


1) visit 배열 외부 정의 및 재사용#

첫 번째 개선 사항으로, visit배열을 BFS함수 외부에서 한 번만 생성하고,
각 BFS마다 재사용하는 방식으로 변경했다.

하지만 단순히 거리를 저장하는 배열로 사용할 경우,
BFS마다 전체 배열을 초기화해야 하므로 시간 오버헤드는 여전히 남아 있었다.


2) 방문 여부와 거리 정보 분리#

이를 위해 visit에는 방문 여부만, 거리 정보는 BFS 노드 내로 분리하여 코드를 구성했다.

이를 통해 visit 배열에는 현재 몇 번째 치즈를 탐색 중인지를 마킹하는 방식으로 값을 기록하여,
배열을 매번 초기화하지 않고도 재사용할 수 있도록 했다.

이를 통해

  • 메모리 할당/해제 비용 제거
  • 배열 초기화 비용 제거

를 모두 달성했다.

현재 2025-01-10 기준, 코드는 Python3 기준 가장 빠른 코드이다.



코드#

Github