Java | JavaScript | TypeScript | C++ | C# | Kotlin | Go Solution.
Java []\nimport java.util.Arrays;\nimport java.util.PriorityQueue;\n\npublic class Solution {\n\n    private record Step(int row, int column, int timeToMoveBetw
```Java []\nimport java.util.Arrays;\nimport java.util.PriorityQueue;\n\npublic class Solution {\n\n    private record Step(int row, int column, int timeToMoveBetweenTwoPoints, int timeFromStart) {}\n\n    private static final int[] UP = {-1, 0};\n    private static final int[] DOWN = {1, 0};\n    private static final int[] LEFT = {0, -1};\n    private static final int[] RIGHT = {0, 1};\n    private static final int[][] MOVES = {UP, DOWN, LEFT, RIGHT};\n\n    private int rows;\n    private int columns;\n\n    private int startRow;\n    private int startColumn;\n\n    private int targetRow;\n    private int targetColumn;\n\n    public int minTimeToReach(int[][] moveTime) {\n        rows = moveTime.length;\n        columns = moveTime[0].length;\n\n        startRow = 0;\n        startColumn = 0;\n\n        targetRow = rows - 1;\n        targetColumn = columns - 1;\n\n        return dijkstraSearchForPathWithMinTime(moveTime);\n    }\n\n    private int dijkstraSearchForPathWithMinTime(int[][] moveTime) {\n        PriorityQueue<Step> minHeapForTime = new PriorityQueue<>((x, y) -> x.timeFromStart - y.timeFromStart);\n        minHeapForTime.add(new Step(startRow, startColumn, 0, 0));\n\n        int[][] minTimeMatrix = new int[rows][columns];\n        for (int row = 0; row < rows; ++row) {\n            Arrays.fill(minTimeMatrix[row], Integer.MAX_VALUE);\n        }\n        minTimeMatrix[startRow][startColumn] = 0;\n\n        while (!minHeapForTime.isEmpty()) {\n            Step current = minHeapForTime.poll();\n            if (current.row == targetRow && current.column == targetColumn) {\n                break;\n            }\n\n            for (int[] move : MOVES) {\n                int nextRow = current.row + move[0];\n                int nextColumn = current.column + move[1];\n                if (!isInMatrix(nextRow, nextColumn)) {\n                    continue;\n                }\n\n                int timeToMoveToNextPoint = getNewTimeToMoveBetweenTwoPoints(current.timeToMoveBetweenTwoPoints);\n                int nextValueForTime = Math.max(timeToMoveToNextPoint + current.timeFromStart,\n                                                timeToMoveToNextPoint + moveTime[nextRow][nextColumn]);\n\n                if (minTimeMatrix[nextRow][nextColumn] > nextValueForTime) {\n                    minTimeMatrix[nextRow][nextColumn] = nextValueForTime;\n                    minHeapForTime.add(new Step(nextRow, nextColumn, timeToMoveToNextPoint, nextValueForTime));\n                }\n            }\n        }\n\n        return minTimeMatrix[targetRow][targetColumn];\n    }\n\n    private boolean isInMatrix(int row, int column) {\n        return row >= 0 && row < rows && column >= 0 && column < columns;\n    }\n\n    private int getNewTimeToMoveBetweenTwoPoints(int prviousTimeToMoveBetweenTwoPoints) {\n        return 1 + (prviousTimeToMoveBetweenTwoPoints % 2);\n    }\n}\n```\n```JavaScript []\n/**\n * @param {number[][]} moveTime\n * @return {number}\n */\nvar minTimeToReach = function (moveTime) {\n    const UP = [-1, 0];\n    const DOWN = [1, 0];\n    const LEFT = [0, -1];\n    const RIGHT = [0, 1];\n\n    this.MOVES = [UP, DOWN, LEFT, RIGHT];\n\n    this.rows = moveTime.length;\n    this.columns = moveTime[0].length;\n\n    this.startRow = 0;\n    this.startColumn = 0;\n\n    this.targetRow = this.rows - 1;\n    this.targetColumn = this.columns - 1;\n\n    return dijkstraSearchForPathWithMinTime(moveTime);\n};\n\n/**\n * @param {number} row\n * @param {number} column\n * @param {number} timeToMoveBetweenTwoPoints \n * @param {number} timeFromStart\n */\nfunction Step(row, column, timeToMoveBetweenTwoPoints, timeFromStart) {\n    this.row = row;\n    this.column = column;\n    this.timeToMoveBetweenTwoPoints = timeToMoveBetweenTwoPoints;\n    this.timeFromStart = timeFromStart;\n}\n\n/**\n * @param {number[][]} moveTime\n * @return {number}\n */\nfunction dijkstraSearchForPathWithMinTime(moveTime) {\n    const minHeapForTime = new MinPriorityQueue({compare: (x, y) => x.timeFromStart - y.timeFromStart});\n    minHeapForTime.enqueue(new Step(this.startRow, this.startColumn, 0, 0));\n\n    const minTimeMatrix = Array.from(new Array(this.rows), () => new Array(this.columns).fill(Number.MAX_SAFE_INTEGER));\n    minTimeMatrix[this.startRow][this.startColumn] = 0;\n\n    while (!minHeapForTime.isEmpty()) {\n        const current = minHeapForTime.dequeue();\n        if (current.row === this.targetRow && current.column === this.targetColumn) {\n            break;\n        }\n\n        for (let move of this.MOVES) {\n            const nextRow = current.row + move[0];\n            const nextColumn = current.column + move[1];\n            if (!isInMatrix(nextRow, nextColumn)) {\n                continue;\n            }\n\n            const timeToMoveToNextPoint = getNewTimeToMoveBetweenTwoPoints(current.timeToMoveBetweenTwoPoints);\n            const nextValueForTime = Math.max(timeToMoveToNextPoint + current.timeFromStart,\n                                              timeToMoveToNextPoint + moveTime[nextRow][nextColumn]);\n\n            if (minTimeMatrix[nextRow][nextColumn] > nextValueForTime) {\n                minTimeMatrix[nextRow][nextColumn] = nextValueForTime;\n                minHeapForTime.enqueue(new Step(nextRow, nextColumn, timeToMoveToNextPoint, nextValueForTime));\n            }\n        }\n    }\n\n    return minTimeMatrix[this.targetRow][this.targetColumn];\n}\n\n/**\n * @param {number} row\n * @param {number} column\n * @return {boolean}\n */\nfunction isInMatrix(row, column) {\n    return row >= 0 && row < this.rows && column >= 0 && column < this.columns;\n}\n\n/**\n * @param {number} prviousTimeToMoveBetweenTwoPoints\n * @return {number}\n */\nfunction getNewTimeToMoveBetweenTwoPoints(prviousTimeToMoveBetweenTwoPoints) {\n    return 1 + (prviousTimeToMoveBetweenTwoPoints % 2);\n}\n```\n```TypeScript []\nfunction minTimeToReach(moveTime: number[][]): number {\n    const UP = [-1, 0];\n    const DOWN = [1, 0];\n    const LEFT = [0, -1];\n    const RIGHT = [0, 1];\n\n    this.MOVES = [UP, DOWN, LEFT, RIGHT];\n\n    this.rows = moveTime.length;\n    this.columns = moveTime[0].length;\n\n    this.startRow = 0;\n    this.startColumn = 0;\n\n    this.targetRow = this.rows - 1;\n    this.targetColumn = this.columns - 1;\n\n    return dijkstraSearchForPathWithMinTime(moveTime);\n};\n\nclass Step {\n\n    row: number;\n    column: number;\n    timeToMoveBetweenTwoPoints: number;\n    timeFromStart: number;\n\n    constructor(row, column, timeToMoveBetweenTwoPoints, timeFromStart) {\n        this.row = row;\n        this.column = column;\n        this.timeToMoveBetweenTwoPoints = timeToMoveBetweenTwoPoints;\n        this.timeFromStart = timeFromStart;\n    }\n}\n\nfunction dijkstraSearchForPathWithMinTime(moveTime: number[][]): number {\n    const minHeapForTime = new MinPriorityQueue({ compare: (x, y) => x.timeFromStart - y.timeFromStart });\n    minHeapForTime.enqueue(new Step(this.startRow, this.startColumn, 0, 0));\n\n    const minTimeMatrix: number[][] = Array.from(new Array(this.rows), () => new Array(this.columns).fill(Number.MAX_SAFE_INTEGER));\n    minTimeMatrix[this.startRow][this.startColumn] = 0;\n\n    while (!minHeapForTime.isEmpty()) {\n        const current = minHeapForTime.dequeue();\n        if (current.row === this.targetRow && current.column === this.targetColumn) {\n            break;\n        }\n\n        for (let move of this.MOVES) {\n            const nextRow = current.row + move[0];\n            const nextColumn = current.column + move[1];\n            if (!isInMatrix(nextRow, nextColumn)) {\n                continue;\n            }\n\n            const timeToMoveToNextPoint = getNewTimeToMoveBetweenTwoPoints(current.timeToMoveBetweenTwoPoints);\n            const nextValueForTime = Math.max(timeToMoveToNextPoint + current.timeFromStart,\n                                              timeToMoveToNextPoint + moveTime[nextRow][nextColumn]);\n\n            if (minTimeMatrix[nextRow][nextColumn] > nextValueForTime) {\n                minTimeMatrix[nextRow][nextColumn] = nextValueForTime;\n                minHeapForTime.enqueue(new Step(nextRow, nextColumn, timeToMoveToNextPoint, nextValueForTime));\n            }\n        }\n    }\n\n    return minTimeMatrix[this.targetRow][this.targetColumn];\n}\n\nfunction isInMatrix(row: number, column: number): boolean {\n    return row >= 0 && row < this.rows && column >= 0 && column < this.columns;\n}\n\nfunction getNewTimeToMoveBetweenTwoPoints(prviousTimeToMoveBetweenTwoPoints: number): number {\n    return 1 + (prviousTimeToMoveBetweenTwoPoints % 2);\n}\n```\n```C++ []\n#include <span>\n#include <limits>\n#include <vector>\n#include <algorithm>\nusing namespace std;\n\nclass Solution {\n\n    struct Step {\n            size_t row{};\n            size_t column{};\n            int timeToMoveBetweenTwoPoints{};\n            int timeFromStart{};\n\n            Step(size_t row, size_t column, int timeToMoveBetweenTwoPoints, int timeFromStart) :\n                    row{ row }, column{ column }, timeToMoveBetweenTwoPoints{ timeToMoveBetweenTwoPoints }, timeFromStart{ timeFromStart } {\n            };\n    };\n\n    struct ComparatorStep {\n            bool operator()(const Step& first, const Step& second) const {\n                    return first.timeFromStart > second.timeFromStart;\n            }\n    };\n\n    static constexpr array<int, 2> UP = { -1, 0 };\n    static constexpr array<int, 2> DOWN = { 1, 0 };\n    static constexpr array<int, 2> LEFT = { 0, -1 };\n    static constexpr array<int, 2> RIGHT = { 0, 1 };\n    static constexpr array< array<int, 2>, 4> MOVES = { UP, DOWN, LEFT, RIGHT };\n\n    size_t rows{};\n    size_t columns{};\n\n    size_t startRow{};\n    size_t startColumn{};\n\n    size_t targetRow{};\n    size_t targetColumn{};\n\npublic:\n    int minTimeToReach(const vector<vector<int>>& moveTime) {\n            rows = moveTime.size();\n            columns = moveTime[0].size();\n\n            startRow = 0;\n            startColumn = 0;\n\n            targetRow = rows - 1;\n            targetColumn = columns - 1;\n\n            return dijkstraSearchForPathWithMinTime(moveTime);\n    }\n\nprivate:\n    int dijkstraSearchForPathWithMinTime(span<const vector<int>> moveTime) const {\n        priority_queue<Step, vector<Step>, ComparatorStep> minHeapForTime;\n        minHeapForTime.emplace(startRow, startColumn, 0, 0);\n\n        vector<vector<int>> minTimeMatrix(rows, vector<int>(columns, numeric_limits<int>::max()));\n        minTimeMatrix[startRow][startColumn] = 0;\n\n        while (!minHeapForTime.empty()) {\n            Step current = minHeapForTime.top();\n            minHeapForTime.pop();\n            if (current.row == targetRow && current.column == targetColumn) {\n                    break;\n            }\n\n            for (const auto& move : MOVES) {\n                size_t nextRow = current.row + move[0];\n                size_t nextColumn = current.column + move[1];\n                if (!isInMatrix(nextRow, nextColumn)) {\n                    continue;\n                }\n\n                int timeToMoveToNextPoint = getNewTimeToMoveBetweenTwoPoints(current.timeToMoveBetweenTwoPoints);\n                int nextValueForTime = max(timeToMoveToNextPoint + current.timeFromStart,\n                                           timeToMoveToNextPoint + moveTime[nextRow][nextColumn]);\n\n                if (minTimeMatrix[nextRow][nextColumn] > nextValueForTime) {\n                    minTimeMatrix[nextRow][nextColumn] = nextValueForTime;\n                    minHeapForTime.emplace(nextRow, nextColumn, timeToMoveToNextPoint, nextValueForTime);\n                }\n            }\n        }\n\n        return minTimeMatrix[targetRow][targetColumn];\n    }\n\n    bool isInMatrix(size_t row, size_t column) const {\n        return  row < rows && column < columns;\n    }\n\n    int getNewTimeToMoveBetweenTwoPoints(int prviousTimeToMoveBetweenTwoPoints) const {\n        return 1 + (prviousTimeToMoveBetweenTwoPoints % 2);\n    }\n};\n```\n```C# []\nusing System;\nusing System.Collections.Generic;\n\npublic class Solution\n{\n    private record Step(int row, int column, int timeToMoveBetweenTwoPoints, int timeFromStart) { }\n\n    private static readonly int[] UP = { -1, 0 };\n    private static readonly int[] DOWN = { 1, 0 };\n    private static readonly int[] LEFT = { 0, -1 };\n    private static readonly int[] RIGHT = { 0, 1 };\n    private static readonly int[][] MOVES = { UP, DOWN, LEFT, RIGHT };\n\n    private int rows;\n    private int columns;\n\n    private int startRow;\n    private int startColumn;\n\n    private int targetRow;\n    private int targetColumn;\n\n    public int MinTimeToReach(int[][] moveTime)\n    {\n        rows = moveTime.Length;\n        columns = moveTime[0].Length;\n\n        startRow = 0;\n        startColumn = 0;\n\n        targetRow = rows - 1;\n        targetColumn = columns - 1;\n\n        return DijkstraSearchForPathWithMinTime(moveTime);\n    }\n\n    private int DijkstraSearchForPathWithMinTime(int[][] moveTime)\n    {\n        PriorityQueue<Step, int> minHeapForTime = new PriorityQueue<Step, int>(\n            Comparer<int>.Create((x, y) => x - y));\n\n        minHeapForTime.Enqueue(new Step(startRow, startColumn, 0, 0), 0);\n\n        int[][] minTimeMatrix = new int[rows][];\n        for (int row = 0; row < rows; ++row)\n        {\n            minTimeMatrix[row] = new int[columns];\n            Array.Fill(minTimeMatrix[row], int.MaxValue);\n        }\n        minTimeMatrix[startRow][startColumn] = 0;\n\n        while (minHeapForTime.Count > 0)\n        {\n            Step current = minHeapForTime.Dequeue();\n            if (current.row == targetRow && current.column == targetColumn)\n            {\n                break;\n            }\n\n            foreach (int[] move in MOVES)\n            {\n                int nextRow = current.row + move[0];\n                int nextColumn = current.column + move[1];\n                if (!IsInMatrix(nextRow, nextColumn))\n                {\n                    continue;\n                }\n\n                int timeToMoveToNextPoint = GetNewTimeToMoveBetweenTwoPoints(current.timeToMoveBetweenTwoPoints);\n                int nextValueForTime = Math.Max(timeToMoveToNextPoint + current.timeFromStart,\n                                                timeToMoveToNextPoint + moveTime[nextRow][nextColumn]);\n\n                if (minTimeMatrix[nextRow][nextColumn] > nextValueForTime)\n                {\n                    minTimeMatrix[nextRow][nextColumn] = nextValueForTime;\n                    minHeapForTime.Enqueue(new Step(nextRow, nextColumn, timeToMoveToNextPoint, nextValueForTime), nextValueForTime);\n                }\n            }\n        }\n\n        return minTimeMatrix[targetRow][targetColumn];\n    }\n\n    private bool IsInMatrix(int row, int column)\n    {\n        return row >= 0 && row < rows && column >= 0 && column < columns;\n    }\n\n    private int GetNewTimeToMoveBetweenTwoPoints(int prviousTimeToMoveBetweenTwoPoints)\n    {\n        return 1 + (prviousTimeToMoveBetweenTwoPoints % 2);\n    }\n}\n```\n```Kotlin []\nimport java.util.PriorityQueue\nimport kotlin.math.max\n\nclass Solution {\n\n    private data class Step(\n        val row: Int,\n        val column: Int,\n        val timeToMoveBetweenTwoPoints: Int,\n        val timeFromStart: Int\n    ) {}\n\n    private companion object {\n        val UP = intArrayOf(-1, 0)\n        val DOWN = intArrayOf(1, 0)\n        val LEFT = intArrayOf(0, -1)\n        val RIGHT = intArrayOf(0, 1)\n        val MOVES = arrayOf(UP, DOWN, LEFT, RIGHT)\n    }\n\n    private var rows = 0\n    private var columns = 0\n\n    private var startRow = 0\n    private var startColumn = 0\n\n    private var targetRow = 0\n    private var targetColumn = 0\n\n    fun minTimeToReach(moveTime: Array<IntArray>): Int {\n        rows = moveTime.size\n        columns = moveTime[0].size\n\n        startRow = 0\n        startColumn = 0\n\n        targetRow = rows - 1\n        targetColumn = columns - 1\n\n        return dijkstraSearchForPathWithMinTime(moveTime)\n    }\n\n    private fun dijkstraSearchForPathWithMinTime(moveTime: Array<IntArray>): Int {\n        val minHeapForTime = PriorityQueue<Step>() { x, y -> x.timeFromStart - y.timeFromStart }\n        minHeapForTime.add(Step(startRow, startColumn, 0, 0))\n\n        val minTimeMatrix = Array<IntArray>(rows) { IntArray(columns) }\n        for (row in 0..<rows) {\n            minTimeMatrix[row].fill(Int.MAX_VALUE, 0, columns)\n        }\n        minTimeMatrix[startRow][startColumn] = 0\n\n        while (!minHeapForTime.isEmpty()) {\n            val current = minHeapForTime.poll()\n            if (current.row == targetRow && current.column == targetColumn) {\n                break\n            }\n\n            for (move in MOVES) {\n                val nextRow = current.row + move[0]\n                val nextColumn = current.column + move[1]\n                if (!isInMatrix(nextRow, nextColumn)) {\n                    continue\n                }\n\n                val timeToMoveToNextPoint = getNewTimeToMoveBetweenTwoPoints(current.timeToMoveBetweenTwoPoints)\n                val nextValueForTime = max(timeToMoveToNextPoint + current.timeFromStart,\n                                           timeToMoveToNextPoint + moveTime[nextRow][nextColumn])\n\n                if (minTimeMatrix[nextRow][nextColumn] > nextValueForTime) {\n                    minTimeMatrix[nextRow][nextColumn] = nextValueForTime\n                    minHeapForTime.add(Step(nextRow, nextColumn, timeToMoveToNextPoint, nextValueForTime))\n                }\n            }\n        }\n\n        return minTimeMatrix[targetRow][targetColumn]\n    }\n\n    private fun isInMatrix(row: Int, column: Int): Boolean {\n        return row in 0..<rows && column in 0..<columns\n    }\n\n    private fun getNewTimeToMoveBetweenTwoPoints(prviousTimeToMoveBetweenTwoPoints: Int): Int {\n        return 1 + (prviousTimeToMoveBetweenTwoPoints % 2)\n    }\n}\n```\n```Go []\npackage main\n\nimport (\n    "container/heap"\n    "fmt"\n    "math"\n)\n\nvar UP = [2]int{-1, 0}\nvar DOWN = [2]int{1, 0}\nvar LEFT = [2]int{0, -1}\nvar RIGHT = [2]int{0, 1}\nvar MOVES = [4][2]int{UP, DOWN, LEFT, RIGHT}\n\nvar rows int\nvar columns int\n\nvar startRow int\nvar startColumn int\n\nvar targetRow int\nvar targetColumn int\n\nfunc minTimeToReach(moveTime [][]int) int {\n    rows = len(moveTime)\n    columns = len(moveTime[0])\n\n    startRow = 0\n    startColumn = 0\n\n    targetRow = rows - 1\n    targetColumn = columns - 1\n\n    return dijkstraSearchForPathWithMinTime(moveTime)\n}\n\nfunc dijkstraSearchForPathWithMinTime(moveTime [][]int) int {\n    minHeapForTime := make(PriorityQueue, 0)\n    step := NewStep(startRow, startColumn, 0, 0)\n    heap.Push(&minHeapForTime, step)\n\n    minTimeMatrix := make([][]int, rows)\n    for row := 0; row < rows; row++ {\n        minTimeMatrix[row] = make([]int, columns)\n        for column := 0; column < columns; column++ {\n            minTimeMatrix[row][column] = math.MaxInt\n        }\n    }\n    minTimeMatrix[startRow][startColumn] = 0\n\n    for len(minHeapForTime) > 0 {\n        current := heap.Pop(&minHeapForTime).(*Step)\n        if current.row == targetRow && current.column == targetColumn {\n            break\n        }\n\n        for _, move := range MOVES {\n            nextRow := current.row + move[0]\n            nextColumn := current.column + move[1]\n            if !isInMatrix(nextRow, nextColumn) {\n                continue\n            }\n\n            timeToMoveToNextPoint := getNewTimeToMoveBetweenTwoPoints(current.timeToMoveBetweenTwoPoints)\n            nextValueForTime := max(timeToMoveToNextPoint+current.timeFromStart,\n                                    timeToMoveToNextPoint+moveTime[nextRow][nextColumn])\n\n            if minTimeMatrix[nextRow][nextColumn] > nextValueForTime {\n                minTimeMatrix[nextRow][nextColumn] = nextValueForTime\n                step := NewStep(nextRow, nextColumn, timeToMoveToNextPoint, nextValueForTime)\n                heap.Push(&minHeapForTime, step)\n            }\n        }\n    }\n\n    return minTimeMatrix[targetRow][targetColumn]\n}\n\nfunc isInMatrix(row int, column int) bool {\n    return row >= 0 && row < rows && column >= 0 && column < columns\n}\n\nfunc getNewTimeToMoveBetweenTwoPoints(prviousTimeToMoveBetweenTwoPoints int) int {\n    return 1 + (prviousTimeToMoveBetweenTwoPoints % 2)\n}\n\ntype Step struct {\n    row                        int\n    column                     int\n    timeToMoveBetweenTwoPoints int\n    timeFromStart              int\n}\n\nfunc NewStep(row int, column int, timeToMoveBetweenTwoPoints int, timeFromStart int) *Step {\n    step := &Step{\n        row:                        row,\n        column:                     column,\n        timeToMoveBetweenTwoPoints: timeToMoveBetweenTwoPoints,\n        timeFromStart:              timeFromStart,\n    }\n    return step\n}\n\ntype PriorityQueue []*Step\n\nfunc (pq PriorityQueue) Len() int {\n    return len(pq)\n}\n\nfunc (pq PriorityQueue) Less(first int, second int) bool {\n    return pq[first].timeFromStart < pq[second].timeFromStart\n}\n\nfunc (pq PriorityQueue) Swap(first int, second int) {\n    pq[first], pq[second] = pq[second], pq[first]\n}\n\nfunc (pq *PriorityQueue) Push(object any) {\n    step := object.(*Step)\n    *pq = append(*pq, step)\n}\n\nfunc (pq *PriorityQueue) Pop() any {\n    step := (*pq)[len(*pq)-1]\n    (*pq)[len(*pq)-1] = nil\n    *pq = (*pq)[0 : len(*pq)-1]\n    return step\n}\n```
['C++', 'Java', 'Go', 'TypeScript', 'Kotlin', 'JavaScript', 'C#']