AtCoder B,C問題をKotlinで解こう - ABC265

当記事ではAtCoder、ABCのB問題ならびにC問題（時々D問題も）のKotlinでの解法を超初心者向けに詳細に解説します。

https://atcoder.jp/contests/abc265/tasks

## [B - Explore](https://atcoder.jp/contests/abc265/tasks/abc265_b)
#### やりたいこと
残り時間を変数に保持して $1..N-1$ のループを回し、次の部屋に行くためのコストと残り時間を比較して処理を進めよう。ボーナス部屋は入力順が部屋の昇順になっているので、FIFOのキューに保持し、キューの先頭と現在位置の部屋を比較して一致する場合、残り時間を増やしてキューを消費しよう。

#### 入力値の取得
```kotlin
    // 入力値の取得
    val (n, m, t) = readLine()!!.split(" ").map { it.toInt() }
    val a = readLine()!!.split(" ").map { it.toInt() }
    // ボーナス部屋の情報を取得し、FIFOのキューに入れる
    val bonus =
        (1..m).map { readLine()!!.split(" ").map { it.toInt() }.let { Bonus(it[0], it[1]) } }.let { LinkedList(it) }


// ボーナス部屋の情報を保持するデータクラス
data class Bonus(val x: Int, val y: Int)
```
#### サンプルコード
:::note
残り時間はIntの範囲を超える可能性があるので、残り時間を保持する変数はLong型にしよう。 
残り時間は **0以下** になるような行動が取れないので、残り時間と次の部屋に行くコストが等しい場合は移動ができないということに注意しよう。
:::
```kotlin:main.kt
import java.util.LinkedList

fun main(args: Array<String>) {
    println(if (getAns()) "Yes" else "No")
}

fun getAns(): Boolean {

    // 入力値の取得
    val (n, m, t) = readLine()!!.split(" ").map { it.toInt() }
    val a = readLine()!!.split(" ").map { it.toInt() }
    // ボーナス部屋の情報を取得し、FIFOのキューに入れる
    val bonus =
        (1..m).map { readLine()!!.split(" ").map { it.toInt() }.let { Bonus(it[0], it[1]) } }.let { LinkedList(it) }

    // 残り時間を変数に入れる
    var remainTime = t.toLong()
    for (i in (1 until n)) {
        // キューの先頭を参照して、現在到達した部屋がボーナス部屋であるかどうかを判定
        if (bonus.isNotEmpty() && bonus.peek().x == i) {
            // ボーナス部屋であった場合、残り時間を増やしてキューを消費する
            remainTime += bonus.pop().y
        }

        // 次の部屋に行くためのコストと現在の残り時間を比較
        if (a[i - 1] >= remainTime) {
            return false
        }
        remainTime -= a[i - 1]
    }
    return true
}
// ボーナス部屋の情報を保持するデータクラス
data class Bonus(val x: Int, val y: Int)

```
## [C - Belt Conveyor](https://atcoder.jp/contests/abc265/tasks/abc265_c)
#### やりたいこと
現在位置のマスの位置（行、列）を保持し、マスに書かれた文字に従って値を変化させよう。
無限に移動し続ける＝ループになるという判定は、過去に到達したマスに再度到達することで行おう。
#### 入力値の取得
```kotlin
    // 入力値の取得
    val (h, w) = readLine()!!.split(" ").map { it.toInt() }
    val g = (1..h).map { readLine()!! }
```
#### サンプルコード　
```kotlin:main.kt
import java.util.LinkedList

fun main(args: Array<String>) {
    println(getAns()?.toString() ?: "-1")
}

fun getAns(): Location? {
    // 入力値の取得
    val (h, w) = readLine()!!.split(" ").map { it.toInt() }
    val g = (1..h).map { readLine()!! }

    // 今まで通過したマスのフラグを保持する2次元配列
    val flag = Array(h) { BooleanArray(w) }

    val queue = LinkedList(listOf(Location(0, 0)))
    var cur = Location(0, 0)
    while (queue.isNotEmpty()) {
        cur = queue.pop()
        if (flag[cur.row][cur.col]) {
            // 一度入ったことのあるマスに再度入ったらループとなる
            return null
        }
        flag[cur.row][cur.col] = true
        // マスに書かれた文字に従って座標更新
        when (g[cur.row][cur.col]) {
            'U' -> {
                if (cur.row > 0) {
                    queue.add(Location(cur.row - 1, cur.col))
                }
            }
            'D' -> {
                if (cur.row < h - 1) {
                    queue.add(Location(cur.row + 1, cur.col))
                }
            }
            'L' -> {
                if (cur.col > 0) {
                    queue.add(Location(cur.row, cur.col - 1))
                }
            }
            else -> {
                if (cur.col < w - 1) {
                    queue.add(Location(cur.row, cur.col + 1))
                }
            }
        }
    }
    return cur
}

// 位置保持のためのクラス
class Location(val row: Int, val col: Int) {
    override fun toString(): String {
        return "${row + 1} ${col + 1}"
    }
}
```