<p>Given an <code>n x n</code> integer matrix <code>grid</code>, return <em>the minimum sum of a <strong>falling path with non-zero shifts</strong></em>.</p>

<p>A <strong>falling path with non-zero shifts</strong> is a choice of exactly one element from each row of <code>grid</code> such that no two elements chosen in adjacent rows are in the same column.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/08/10/falling-grid.jpg" style="width: 244px; height: 245px;" />
<pre>
<strong>Input:</strong> grid = [[1,2,3],[4,5,6],[7,8,9]]
<strong>Output:</strong> 13
<strong>Explanation:</strong> 
The possible falling paths are:
[1,5,9], [1,5,7], [1,6,7], [1,6,8],
[2,4,8], [2,4,9], [2,6,7], [2,6,8],
[3,4,8], [3,4,9], [3,5,7], [3,5,9]
The falling path with the smallest sum is&nbsp;[1,5,7], so the answer is&nbsp;13.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> grid = [[7]]
<strong>Output:</strong> 7
</pre>

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

<ul>
	<li><code>n == grid.length == grid[i].length</code></li>
	<li><code>1 &lt;= n &lt;= 200</code></li>
	<li><code>-99 &lt;= grid[i][j] &lt;= 99</code></li>
</ul>

class Solution:
    def minFallingPathSum(self, grid: List[List[int]]) -> int:
        n = len(grid)
        if n == 1:
            return grid[0][0]
        if n == 2:
            return min(grid[0][0]+grid[1][1],grid[0][1]+ grid[1][0])
        def get_three_smallest(lst):
                first = second = third = float('inf')
                first_index = second_index = third_index = -1
                
                for i,num in enumerate(lst):
                    if num < first:
                        third, third_index = second, second_index
                        second, second_index = first, first_index
                        first, first_index = num, i
                    elif num < second and i != first_index:  # Ensure it's not the same element as the first smallest
                        third, third_index = second, second_index
                        second, second_index = num, i
                    elif num < third and i != first_index and i != second_index:  # Ensure it's not the same as the first or second smallest
                        third, third_index = num, i
                
                return set([first, second, third])
        smallest_3_values = [get_three_smallest(arr) for arr in grid]
        @cache
        def dp(row,col):
            if row == n -1:
                return 0
            answer = float('inf')
            for index, elem in enumerate(grid[row+1]):
                if elem in smallest_3_values[row+1] and col != index:
                    answer = min(answer,elem + dp(row+1,index))
            return answer
        answer = float('inf')
        for index, elem in enumerate(grid[0]):
            if elem in smallest_3_values[0]:
                answer = min(elem + dp(0,index),answer)
        return answer

27000