문제
청소년 상어는 더욱 자라 어른 상어가 되었다. 상어가 사는 공간에 더 이상 물고기는 오지 않고 다른 상어들만이 남아있다. 상어에는 1 이상 M 이하의 자연수 번호가 붙어 있고, 모든 번호는 서로 다르다. 상어들은 영역을 사수하기 위해 다른 상어들을 쫓아내려고 하는데, 1의 번호를 가진 어른 상어는 가장 강력해서 나머지 모두를 쫓아낼 수 있다.
N×N 크기의 격자 중 M개의 칸에 상어가 한 마리씩 들어 있다. 맨 처음에는 모든 상어가 자신의 위치에 자신의 냄새를 뿌린다. 그 후 1초마다 모든 상어가 동시에 상하좌우로 인접한 칸 중 하나로 이동하고, 자신의 냄새를 그 칸에 뿌린다. 냄새는 상어가 k번 이동하고 나면 사라진다.
각 상어가 이동 방향을 결정할 때는, 먼저 인접한 칸 중 아무 냄새가 없는 칸의 방향으로 잡는다. 그런 칸이 없으면 자신의 냄새가 있는 칸의 방향으로 잡는다. 이때 가능한 칸이 여러 개일 수 있는데, 그 경우에는 특정한 우선순위를 따른다. 우선순위는 상어마다 다를 수 있고, 같은 상어라도 현재 상어가 보고 있는 방향에 따라 또 다를 수 있다. 상어가 맨 처음에 보고 있는 방향은 입력으로 주어지고, 그 후에는 방금 이동한 방향이 보고 있는 방향이 된다.
모든 상어가 이동한 후 한 칸에 여러 마리의 상어가 남아 있으면, 가장 작은 번호를 가진 상어를 제외하고 모두 격자 밖으로 쫓겨난다.
이 과정을 반복할 때, 1번 상어만 격자에 남게 되기까지 몇 초가 걸리는지를 구하는 프로그램을 작성하시오.
출력
1번 상어만 격자에 남게 되기까지 걸리는 시간을 출력한다. 단, 1,000초가 넘어도 다른 상어가 격자에 남아 있으면 -1을 출력한다.
풀이
꽤 복잡한 편에 속하는 까다로운 시뮬레이션
문제이다. 로직 자체는 매우 단순하나, 조건과 정보의 양이 많다. 상어 방향의 우선순위가 상어의 현재 방향에 따라 다르기 때문에 3차원 배열
을 통해 이를 저장해주어야 한다. 또 상어가 냄새를 뿌리므로 냄새를 저장하는 2차원 배열
을 따로 선언해야하며, 상어가 한 칸에 여러마리 있는 상황이 존재하므로 상어를 원소로 갖는 vector
의 2차원 배열
도 필요하다. 그리고 칸 마다 가장 숫자가 작은 상어만 살아남으므로 이를 어떻게 효율적으로 구현할지도 고민해야 할 포인트다.
우선 먼저 캐치해야 할 포인트는 상어가 동시에 움직이므로, 상어를 격자별로 여러마리 저장할 수 있는 자료구조에 임시적으로 옮겨놓고 격자마다 최소 번호를 갖고 있는 상어를 최종 상태를 저장하는 자료구조에 저장해야 한다는 것이다. 전자는 상어 구조체를 원소로 갖는 vector
를, 후자는 격자별로 상어가 한 마리씩만 들어있으므로 일반적인 상어 배열을 선언하면 됨을 알 수 있다.
격자 별로 가장 작은 번호의 상어를 골라내는 방법은 다음과 같은 방법들을 떠올릴 수 있다.
- 원소의 삭제가 비교적 빠른
list
자료구조와정렬
을 이용 우선순위 큐
자료구조를 이용해 상어가 추가될 때마다 비교vector
에서 단순히 모든 원소를 순차적으로 비교해 최소 번호 찾기
이 문제와 같이 상어의 개수가 적은 형태에서는 실행 시간에 있어서 위 세가지 방법에 큰 차이는 없겠지만 아무래도 항상 선형 시간복잡도 O(N) 을 보장하고 구현이 단순한 마지막 3번째 방법이 가장 나은 것을 알 수 있다.
냄새를 기록하는 배열에서는 냄새의 번호와 함께 냄새의 유지 시간도 저장해야하므로 pair
객체를 사용하였다.
이 후 반복문을 통해 남은 상어의 수를 확인하며 경과시간을 계속 올려주면 된다.
전체 코드
1 |
|
- Post link: https://blog.yjyoon.dev/boj/2020/12/14/boj-19237/
- Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.