<p>Given an <code>n x n</code> array of integers <code>matrix</code>, return <em>the <strong>minimum sum</strong> of any <strong>falling path</strong> through</em> <code>matrix</code>.</p>

<p>A <strong>falling path</strong> starts at any element in the first row and chooses the element in the next row that is either directly below or diagonally left/right. Specifically, the next element from position <code>(row, col)</code> will be <code>(row + 1, col - 1)</code>, <code>(row + 1, col)</code>, or <code>(row + 1, col + 1)</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/11/03/failing1-grid.jpg" style="width: 499px; height: 500px;" />
<pre>
<strong>Input:</strong> matrix = [[2,1,3],[6,5,4],[7,8,9]]
<strong>Output:</strong> 13
<strong>Explanation:</strong> There are two falling paths with a minimum sum as shown.
</pre>

<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/11/03/failing2-grid.jpg" style="width: 164px; height: 365px;" />
<pre>
<strong>Input:</strong> matrix = [[-19,57],[-40,-5]]
<strong>Output:</strong> -59
<strong>Explanation:</strong> The falling path with a minimum sum is shown.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>n == matrix.length == matrix[i].length</code></li>
	<li><code>1 &lt;= n &lt;= 100</code></li>
	<li><code>-100 &lt;= matrix[i][j] &lt;= 100</code></li>
</ul>

class Solution:
    def minFallingPathSum(self, matrix: List[List[int]]) -> int:
        
        rows = len(matrix)
        cols = len(matrix[0])

        dp = [[None] * cols for _ in range(rows)]

        def f(i,j):
            try:
                if dp[i][j] != None:
                    return dp[i][j]
            except: 
                pass

            if i == 0:
                dp[i][j] = matrix[i][j]
                return matrix[i][j]
            
            else:
                up = [(i-1, j-1), (i-1, j), (i-1, j+1)]
                up_f = []
                for (pos_i, pos_j) in up:
                    if (pos_i >= 0) and (pos_j >= 0) and (pos_j < len(matrix)): 
                        up_f.append((pos_i, pos_j))
                
                res = None 
                
                if len(up_f) == 3:
                    res= matrix[i][j] + min(   f(i = up_f[0][0], j = up_f[0][1]), 
                                               f(i = up_f[1][0], j = up_f[1][1]), 
                                               f(i = up_f[2][0], j = up_f[2][1])
                                              )
                                            
                elif len(up_f) == 2:
                    res= matrix[i][j] + min(   f(i = up_f[0][0], j = up_f[0][1]), 
                                               f(i = up_f[1][0], j = up_f[1][1]))
                
                elif len(up_f) == 1:
                    res= matrix[i][j] + min( f(i = up_f[0][0], j = up_f[0][1]) )

                dp[i][j] = res 
                return res                
        
        mini = None 
        for k in range(0, cols):            
            curr = f(rows - 1, k)
            if mini == None or curr < mini:
                mini = curr 
        return mini

        
19900