<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:
        # n = len(matrix)
        # dp = [[None for i in range(n)] for j in range(n)]

        # def minFallingPathSumUtil(i, j):
        #     if j < 0 or j > n-1:
        #         return int(1e9)

        #     if i == 0:
        #         dp[0][j] = matrix[0][j]
        #         return dp[0][j]

        #     if dp[i][j] != None:
        #         return dp[i][j]
            
        #     up = minFallingPathSumUtil(i-1, j)
        #     left = minFallingPathSumUtil(i-1, j-1)
        #     right = minFallingPathSumUtil(i-1, j+1)

        #     dp[i][j] = matrix[i][j] + min(up, min(left, right))
        #     return dp[i][j]
        
        # minVal = int(1e9)
        # for j in range(n):
        #     minVal = min(minFallingPathSumUtil(n-1, j), minVal)

        # return minVal

        n = len(matrix)
        dp = [[None for c in range(n)] for r in range(n)]

        def minFallingPathSumUtil(r, c):
            if c < 0 or c > n-1:
                return int(1e9)
            
            if r == 0:
                dp[r][c] = matrix[r][c]
                return dp[r][c]
            
            if dp[r][c] != None:
                return dp[r][c]
            
            up = minFallingPathSumUtil(r-1, c)
            left = minFallingPathSumUtil(r-1, c-1)
            right = minFallingPathSumUtil(r-1, c+1)

            dp[r][c] = matrix[r][c] + min(up, left, right)
            return dp[r][c]

        minVal = int(1e9)
        for c in range(n):
            minVal = min(minFallingPathSumUtil(n-1, c), minVal)
        
        return minVal
18700