[문제]
16920번: 확장 게임
구사과와 친구들이 확장 게임을 하려고 한다. 이 게임은 크기가 N×M인 격자판 위에서 진행되며, 각 칸은 비어있거나 막혀있다. 각 플레이어는 하나 이상의 성을 가지고 있고, 이 성도 격자판 위
www.acmicpc.net
[깃허브]
GitHub - Dev-Joco/algorithm-kotlin: Algorithm(Kotlin)
Algorithm(Kotlin). Contribute to Dev-Joco/algorithm-kotlin development by creating an account on GitHub.
github.com
문제 요약
- 최대 9명의 선수들이 각자의 성(castle)을 매 라운드마다 주어진 조건 S(i) 크기 만큼씩 확장해 나가는 게임.
제한 조건
- 시간 제한: 2초
- 메모리 제한: 512MB
- 1 ≤ N, M ≤ 1,000
- 1 ≤ P ≤ 9
- 1 ≤ Si ≤ 10^9
풀이
- 매 라운드마다 1번 선수 ~ 9번 선수까지 순서대로 한 턴씩 BFS로 확장.
- 각 선수마다 BFS를 진행해야 하기 때문에 P개(참가 인원수)의 큐를 사용.
- i번 선수가 각 턴마다 한 번에 확장시킬 수 있는 거리의 크기는 S(i)이며, 각 턴마다 S(i)번 BFS를 돌리면 됨.
- (팁) BFS 할 때, 보드판에 성을 확장시킬 때마다 각 선수들의 번호로 바꿔주고, 빈 칸(.)으로만 전진이 가능하게 하면 visited를 쓸 필요 없음.
- 모든 선수들의 큐가 전부 비워지면 종료.
[Solution.kt]
import java.util.ArrayDeque
private const val BLANK = -1
private const val BARRIER = 9
private val DR = intArrayOf(0, -1, 0, 1)
private val DC = intArrayOf(-1, 0, 1, 0)
fun main() {
// 1 ≤ N, M ≤ 1,000
// 1 ≤ P ≤ 9
// 1 ≤ Si ≤ 10^9
val (N, M, P) = readLine()!!.split(" ").map { it.toInt() }
val S = readLine()!!.split(" ")
// S(i) 최댓값이 10^9 로 너무 큰 수이며
// 성을 확장할 때 board 에서 최대 거리는 N + M 이므로
.map { Math.min(it.toInt(), N + M) }
.toIntArray()
val board: Array<IntArray> = Array(N) { intArrayOf() }
for (i in 0 until N) {
board[i] = readLine()!!
.map { when (it) {
'.' -> BLANK
'#' -> BARRIER
else -> it.digitToInt() - 1
}}
.toIntArray()
}
solution(N, M, P, S, board).let {
println(it.joinToString(" "))
}
}
private fun solution(
N: Int, M: Int, P: Int,
S: IntArray,
board: Array<IntArray>
): IntArray {
val castleCount = IntArray(P)
// 각 선수마다 큐 생성
val eachQueue = Array(P) { ArrayDeque<IntArray>() }
// 초기 보드에 놓여진 성의 위치를 각 선수 큐에 넣기
for (r in 0 until N) for (c in 0 until M) {
val number = board[r][c]
if (number !in 0..8)
continue
eachQueue[number].offer(intArrayOf(r, c))
castleCount[number] += 1
}
// 모든 선수의 큐가 Empty 일 때까지
while (eachQueue.any { it.isNotEmpty() }) {
// 각 선수마다 BFS
for (player in 0 until P) {
val queue = eachQueue[player]
if (queue.isEmpty())
continue
castleCount[player] += bfs(N, M, S, board, player, queue)
}
}
return castleCount
}
private fun bfs(
N: Int, M: Int,
S: IntArray,
board: Array<IntArray>,
player: Int,
queue: ArrayDeque<IntArray>
): Int {
var expandedCount = 0
// 각자의 턴마다 i번의 선수는 BFS 를 S(i) 번 반복함
for (si in 1..S[player]) {
for (q in queue.indices) {
val (r, c) = queue.poll()
for (dir in 0..3) {
val nr = r + DR[dir]
val nc = c + DC[dir]
if (nr !in 0 until N || nc !in 0 until M || board[nr][nc] != BLANK )
continue
board[nr][nc] = player
queue.offer(intArrayOf(nr, nc))
expandedCount += 1
}
}
if (queue.isEmpty())
break
}
return expandedCount
}
'3. 알고리즘 > BOJ' 카테고리의 다른 글
[Joco][백준/BOJ] 1385 번: 벌집 - Kotlin (0) | 2022.08.05 |
---|---|
[Joco][백준/BOJ] 15653 번: 구슬 탈출 4 (0) | 2022.08.03 |
[Joco][백준/BOJ] 1175 번: 배달 (0) | 2022.07.17 |
[Joco][백준/BOJ] 17071 번: 숨바꼭질 5 (Kotlin) (0) | 2022.07.17 |
[Joco][백준/BOJ] 1525 번: 퍼즐 (Kotlin) (0) | 2022.07.17 |
댓글