BFS를 이용해서 풀었던 문제

(BFS가 익숙치 않아 코드가 좀 난잡한점 양해 부탁드립니다.)

링크 : https://www.acmicpc.net/problem/16236

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가

www.acmicpc.net

import java.io.BufferedReader
import java.io.FileInputStream
import java.io.InputStreamReader
import java.util.PriorityQueue

val MX = arrayOf(0,0,-1,1)//상하좌우
val MY = arrayOf(1,-1,0,0)//상하좌우
lateinit var Q : ArrayDeque<Point>
lateinit var priorityQueue: PriorityQueue<Point>
lateinit var dp : Array<Array<Int>> //BFS 이동 흔적
var answer = 0
var time = 0
var sharkLevel = 2
var eatCount = 0
fun main() {
    val br = BufferedReader(InputStreamReader(System.`in`))
    val N = br.readLine().toInt()
    val map = Array(N){br.readLine().split(" ").map { it.toInt() }.toMutableList()}

    dp = Array(N){Array(N){0}}
    //먹잇감 우선순위 : 거리 작은 순 > Y작은 순  > X작은 순
    priorityQueue = PriorityQueue<Point>(
        compareBy<Point> { it.y }
        .thenBy { it.x })

    //BFS
    //StartPoint 큐에 넣음
    Q = ArrayDeque<Point>()
    for (r in map.indices) {
        for (c in map[r].indices) {
            if(map[r][c] == 9){
                map[r][c] = 0
                Q.add(Point(r,c,0))
            }
        }
    }
    while (Q.isNotEmpty()){

        if(Q.first().time == time){
            //큐에서 꺼냄
            val point = Q.removeFirst()
            //연결된 곳 순회 (상하좌우) //목적지를 찾는 과정
            for (i in 0..3){
                val nextY = point.y + MY[i]; val nextX = point.x + MX[i]
                // 맵안인가?
                if((nextY in 0 until N) && (nextX in 0 until N)){
                    //레벨이 낮거나 같은 물고기인가? (혹은 빈칸) && 가지 않았던 길인가?
                    if((map[nextY][nextX] <= sharkLevel) && (dp[nextY][nextX] == 0)){
                        //체크인
                        dp[nextY][nextX] = dp[point.y][point.x] + 1
                        //먹잇감인가? 맞으면 P.Q에도 넣음
                        if((map[nextY][nextX] != 0) && (map[nextY][nextX] < sharkLevel)){
                            priorityQueue.add(Point(nextY,nextX,dp[nextY][nextX]))
                        }
                        //아니면 일반 큐에만 넣음
                        Q.add(Point(nextY,nextX,dp[nextY][nextX]))
                    }
                }
            }
        //한 사이클로 나올 수 있는 큐가 다 나왔다면
        }else{
            time++ //전체 시간 갱신
            //P.Q에 들어가있는 우선순위가 가장 높은 장소로 이동
            if (priorityQueue.isNotEmpty()) {
                val target = priorityQueue.poll()
                //맵 빈칸 표시
                map[target.y][target.x] = 0
                eatCount++
                //levelUp 가능 여부 체크
                if (eatCount == sharkLevel) {
                    sharkLevel++
                    eatCount = 0
                }
                //옮겨진 위치에서 다시 우선순위 높은 지점을 탐색해야함으로 초기화
                Q.clear()
                priorityQueue.clear()
                answer += time //시간 백업
                dp = Array(N) { Array(N) { 0 } }
                //현재 위치에서 다시 BFS 탐색
                Q.add(Point(target.y, target.x, 0))
                time = 0
            }
        }
        //P.Q가 비어 있으면 일반큐 순회
    }
    println(answer)
}
class Point (val y :Int = 0,
             val x :Int =0,
             val time :Int =0) //time : 현재 위치로부터의 거리 (= 걸린 시간)

'Algorithm_Kotlin' 카테고리의 다른 글

[Kotlin] BOJ1713 후보 추천하기  (0) 2022.08.04
[Kotlin] BOJ1062 가르침  (0) 2022.08.04
[Kotlin] BOJ3055 탈출  (0) 2022.08.02
[Kotlin] BOJ14476 최대공약수 하나 빼기  (0) 2022.08.02
[Kotlin] BOJ3425 고스택  (0) 2022.08.01