LeetCode in Kotlin

3797. Count Routes to Climb a Rectangular Grid

Hard

You are given a string array grid of size n, where each string grid[i] has length m. The character grid[i][j] is one of the following symbols:

You want to count the number of different routes to climb grid. Each route must start from any cell in the bottom row (row n - 1) and end in the top row (row 0).

However, there are some constraints on the route.

Return an integer denoting the number of such routes. Since the answer may be very large, return it modulo 109 + 7.

Example 1:

Input: grid = [”..”,”#.”], d = 1

Output: 2

Explanation:

We label the cells we visit in the routes sequentially, starting from 1. The two routes are:

.2 #1

32 #1

We can move from the cell (1, 1) to the cell (0, 1) because the Euclidean distance is sqrt((1 - 0)2 + (1 - 1)2) = sqrt(1) <= d.

However, we cannot move from the cell (1, 1) to the cell (0, 0) because the Euclidean distance is sqrt((1 - 0)2 + (1 - 0)2) = sqrt(2) > d.

Example 2:

Input: grid = [”..”,”#.”], d = 2

Output: 4

Explanation:

Two of the routes are given in example 1. The other two routes are:

2. #1

23 #1

Note that we can move from (1, 1) to (0, 0) because the Euclidean distance is sqrt(2) <= d.

Example 3:

Input: grid = [”#”], d = 750

Output: 0

Explanation:

We cannot choose any cell as the starting cell. Therefore, there are no routes.

Example 4:

Input: grid = [”..”], d = 1

Output: 4

Explanation:

The possible routes are:

.1

1.

12

21

Constraints:

Solution

import kotlin.math.min
import kotlin.math.sqrt

class Solution {
    fun numberOfRoutes(grid: Array<String>, d: Int): Int {
        val n = grid.size
        val m = grid[0].length
        val mod: Long = 1000000007
        var dp: LongArray? = null
        for (i in n - 1 downTo 0) {
            val r = grid[i]
            if (dp == null) {
                val init = LongArray(m)
                init.fill(1)
                dp = f(init, 0, r, m, mod)
            } else {
                val d2 = sqrt(d.toDouble() * d - 1).toInt()
                dp = f(dp, d2, r, m, mod)
            }
            dp = f(dp, d, r, m, mod)
        }
        var res: Long = 0
        for (v in dp!!) {
            res = (res + v) % mod
        }
        return (res).toInt()
    }

    private fun f(dp: LongArray, dist: Int, r: String, m: Int, mod: Long): LongArray {
        val dp2 = LongArray(m)
        var window: Long = 0
        for (k in 0..min(m - 1, dist)) {
            window += dp[k]
        }
        dp2[0] = window
        for (j in 1..<m) {
            window = dp2[j - 1]
            if (j - dist - 1 >= 0) {
                window -= dp[j - dist - 1]
            }
            if (j + dist < m) {
                window += dp[j + dist]
            }
            dp2[j] = window
        }
        for (j in 0..<m) {
            dp2[j] = if (r[j] == '#') 0 else dp2[j] % mod
        }
        return dp2
    }
}