문제
상어 중학교의 코딩 동아리에서 게임을 만들었다. 이 게임은 크기가 N×N인 격자에서 진행되고, 초기에 격자의 모든 칸에는 블록이 하나씩 들어있고, 블록은 검은색 블록, 무지개 블록, 일반 블록이 있다. 일반 블록은 M가지 색상이 있고, 색은 M이하의 자연수로 표현한다. 검은색 블록은 -1, 무지개 블록은 0으로 표현한다. (i, j)는 격자의 i번 행, j번 열을 의미하고, |r1 - r2| + |c1 - c2| = 1
을 만족하는 두 칸 (r1, c1)과 (r2, c2)를 인접한 칸이라고 한다.
블록 그룹은 연결된 블록의 집합이다. 그룹에는 일반 블록이 적어도 하나 있어야 하며, 일반 블록의 색은 모두 같아야 한다. 검은색 블록은 포함되면 안 되고, 무지개 블록은 얼마나 들어있든 상관없다. 그룹에 속한 블록의 개수는 2보다 크거나 같아야 하며, 임의의 한 블록에서 그룹에 속한 인접한 칸으로 이동해서 그룹에 속한 다른 모든 칸으로 이동할 수 있어야 한다. 블록 그룹의 기준 블록은 무지개 블록이 아닌 블록 중에서 행의 번호가 가장 작은 블록, 그러한 블록이 여러개면 열의 번호가 가장 작은 블록이다.
오늘은 이 게임에 오토 플레이 기능을 만드려고 한다. 오토 플레이는 다음과 같은 과정이 블록 그룹이 존재하는 동안 계속해서 반복되어야 한다.
- 크기가 가장 큰 블록 그룹을 찾는다. 그러한 블록 그룹이 여러 개라면 포함된 무지개 블록의 수가 가장 많은 블록 그룹, 그러한 블록도 여러개라면 기준 블록의 행이 가장 큰 것을, 그 것도 여러개이면 열이 가장 큰 것을 찾는다.
- 1에서 찾은 블록 그룹의 모든 블록을 제거한다. 블록 그룹에 포함된 블록의 수를 B라고 했을 때, B2점을 획득한다.
- 격자에 중력이 작용한다.
- 격자가 90도 반시계 방향으로 회전한다.
- 다시 격자에 중력이 작용한다.
격자에 중력이 작용하면 검은색 블록을 제외한 모든 블록이 행의 번호가 큰 칸으로 이동한다. 이동은 다른 블록이나 격자의 경계를 만나기 전까지 계속 된다.
오토 플레이가 모두 끝났을 때 획득한 점수의 합을 구해보자.
입력
첫째 줄에 격자 한 변의 크기 N, 색상의 개수 M이 주어진다.
둘째 줄부터 N개의 줄에 격자의 칸에 들어있는 블록의 정보가 1번 행부터 N번 행까지 순서대로 주어진다. 각 행에 대한 정보는 1열부터 N열까지 순서대로 주어진다. 입력으로 주어지는 칸의 정보는 -1, 0, M이하의 자연수로만 이루어져 있다.
출력
첫째 줄에 획득한 점수의 합을 출력한다.
제한
- 1 ≤ N ≤ 20
- 1 ≤ M ≤ 5
풀이
본 문제와 세트 문제인 상어 초등학교와 아주 유사한 문제이다. 동일하게 구현
과 시뮬레이션
에 기반한 문제이지만, 그래프 탐색
이 가미되었고 격자 내에서의 추가적인 구현 및 조건이 붙었다. 문제의 핵심은 매 턴마다 알맞은 블록 그룹을 찾아내는 것이다. 우선 문제에서 제시한 조건이 상당히 많으므로 문제를 주의깊게 읽어야한다. 요약하자면 검은색 블록은 벽이나 마찬가지이고, 무지개 블록은 그 어느 색이던 될 수 있다. 이것이 조건의 핵심이고, 기준 블록은 그룹 내의 블록 중에서 가장 상단, 그리고 좌측에 있는 블록이다.
모든 블록 그룹들을 탐색하려면 모든 좌표에서 DFS
또는 BFS
를 수행해야 할 것이다. 그런데 이 때 주의해야 할 점이 있다. 보통 모든 좌표에서 그래프 탐색
을 할 경우, visited
와 같은 방문 기록을 저장하는 배열을 두고 이미 한 번이라도 방문했던 좌표에서는 효율성을 위해 아예 탐색을 하지 않는 경우가 많은데 이 문제에서는 이 방식으로 하면 틀린다. 바로 무지개 블록 때문이다. 무지개 블록은 여러 블록 그룹들끼리 공유될 수 있기 때문에, 매 좌표마다 그래프 탐색이 끝나면 visited
배열을 초기화하여 무지개 블록이 다른 블록 그룹 탐색에서도 방문될 수 있게끔 해야한다.
매 턴마다 알맞은 블록 그룹을 골라내는 작업은 구조체
와 정렬
을 이용하면 간단하다. 이러한 블록 그룹들을 저장하는 구조체를 선언하고, 문제의 조건에 맞게 비교 연산자
를 오버라이딩 한다. 그러면 매 턴마다 모든 블록 그룹 후보들을 벡터
에 넣고 정렬하면 벡터의 맨 앞에서 가장 알맞은 블록 그룹을 찾을 수 있다.
그리고 문제를 푸는 과정에서 블록 그룹을 삭제할 때 격자에서 빈 칸을 정의할 일이 생긴다. 이는 문제에서 사용되지 않은 -2
와 같은 음수로 표현해주면 코드 작성 과정에서 검은색 블록과 빈 칸을 쉽게 묶을 수 있어 효율적이다.
전체 코드
1 |
|
- Post link: https://blog.yjyoon.dev/boj/2022/01/02/boj-21609/
- Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.