package LeetCode_931
/**
* 931. Minimum Falling Path Sum
* https://leetcode.com/problems/minimum-falling-path-sum/
*
* Given a square array of integers A, we want the minimum sum of a falling path through A.
A falling path starts at any element in the first row, and chooses one element from each row.
The next row's choice must be in a column that is different from the previous row's column by at most one.
Example 1:
Input:
[
[1,2,3],
[4,5,6],
[7,8,9]
]
Output: 12
Explanation:
The possible falling paths are:
[1,4,7], [1,4,8], [1,5,7], [1,5,8], [1,5,9]
[2,4,7], [2,4,8], [2,5,7], [2,5,8], [2,5,9], [2,6,8], [2,6,9]
[3,5,7], [3,5,8], [3,5,9], [3,6,8], [3,6,9]
The falling path with the smallest sum is [1,4,7], so the answer is 12.
Constraints:
1. 1 <= A.length == A[0].length <= 100
2. -100 <= A[i][j] <= 100
* */
class Solution {
/*
* solution : DP, Bottom-Up, for example array is:
* [
[1,2,3],
[4,5,6],
[7,8,9]
]
fill new value from second row, the value of current i,j is: current value + min(A[i-1][j], A[i-1][j+1])
[1,2,3],
[5,6,8],//<-this row after fill by: 4+min(1,2), 5+min(1,min(2,3)), 6+min(2,3)
[12,13,15],//<-this row after fill by: 7+min(5,6), 8+min(5,min(6,8)), 9+min(6,8)
result is minimum in last row
Time complexity:O(nn), Space complexity:O(1)
* */
fun minFallingPathSum(A: Array<IntArray>): Int {
if (A == null || A.isEmpty()) {
return 0
}
val n = A.size
if (n == 1) {
return A[0][0]
}
for (i in 1 until n) {//start from second row
for (j in 0 until n) {
if (j == 0) {
A[i][j] += Math.min(A[i - 1][j], A[i - 1][j + 1])
} else if (j == n - 1) {
A[i][j] += Math.min(A[i - 1][j - 1], A[i - 1][j])
} else {
A[i][j] += Math.min(A[i - 1][j - 1], Math.min(A[i - 1][j + 1], A[i - 1][j]))
}
}
}
var result = Int.MAX_VALUE
for (cols in 0 until n) {
result = Math.min(result, A[n - 1][cols])
}
return result
}
}