<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)

        # Start with the last row as the initial dp state
        dp = grid[-1][:]

        # Iterate upwards, processing blocks of 10 rows at a time
        row = n - 2
        while row >= 0:
            # Process 10 rows (unroll the loop for better efficiency)

            # Unroll row 1 (if row exists)
            if row >= 0:
                min1, min2 = float('inf'), float('inf')
                min1_col = -1
                for col in range(n):
                    if dp[col] < min1:
                        min2 = min1
                        min1 = dp[col]
                        min1_col = col
                    elif dp[col] < min2:
                        min2 = dp[col]

                new_dp1 = [0] * n
                for col in range(n):
                    if col != min1_col:
                        new_dp1[col] = grid[row][col] + min1
                    else:
                        new_dp1[col] = grid[row][col] + min2

                dp = new_dp1
                row -= 1

            # Unroll row 2
            if row >= 0:
                min1, min2 = float('inf'), float('inf')
                min1_col = -1
                for col in range(n):
                    if dp[col] < min1:
                        min2 = min1
                        min1 = dp[col]
                        min1_col = col
                    elif dp[col] < min2:
                        min2 = dp[col]

                new_dp2 = [0] * n
                for col in range(n):
                    if col != min1_col:
                        new_dp2[col] = grid[row][col] + min1
                    else:
                        new_dp2[col] = grid[row][col] + min2

                dp = new_dp2
                row -= 1

            # Unroll row 3
            if row >= 0:
                min1, min2 = float('inf'), float('inf')
                min1_col = -1
                for col in range(n):
                    if dp[col] < min1:
                        min2 = min1
                        min1 = dp[col]
                        min1_col = col
                    elif dp[col] < min2:
                        min2 = dp[col]

                new_dp3 = [0] * n
                for col in range(n):
                    if col != min1_col:
                        new_dp3[col] = grid[row][col] + min1
                    else:
                        new_dp3[col] = grid[row][col] + min2

                dp = new_dp3
                row -= 1

            # Unroll row 4
            if row >= 0:
                min1, min2 = float('inf'), float('inf')
                min1_col = -1
                for col in range(n):
                    if dp[col] < min1:
                        min2 = min1
                        min1 = dp[col]
                        min1_col = col
                    elif dp[col] < min2:
                        min2 = dp[col]

                new_dp4 = [0] * n
                for col in range(n):
                    if col != min1_col:
                        new_dp4[col] = grid[row][col] + min1
                    else:
                        new_dp4[col] = grid[row][col] + min2

                dp = new_dp4
                row -= 1

            # Unroll row 5
            if row >= 0:
                min1, min2 = float('inf'), float('inf')
                min1_col = -1
                for col in range(n):
                    if dp[col] < min1:
                        min2 = min1
                        min1 = dp[col]
                        min1_col = col
                    elif dp[col] < min2:
                        min2 = dp[col]

                new_dp5 = [0] * n
                for col in range(n):
                    if col != min1_col:
                        new_dp5[col] = grid[row][col] + min1
                    else:
                        new_dp5[col] = grid[row][col] + min2

                dp = new_dp5
                row -= 1

            # Unroll row 6
            if row >= 0:
                min1, min2 = float('inf'), float('inf')
                min1_col = -1
                for col in range(n):
                    if dp[col] < min1:
                        min2 = min1
                        min1 = dp[col]
                        min1_col = col
                    elif dp[col] < min2:
                        min2 = dp[col]

                new_dp6 = [0] * n
                for col in range(n):
                    if col != min1_col:
                        new_dp6[col] = grid[row][col] + min1
                    else:
                        new_dp6[col] = grid[row][col] + min2

                dp = new_dp6
                row -= 1

            # Unroll row 7
            if row >= 0:
                min1, min2 = float('inf'), float('inf')
                min1_col = -1
                for col in range(n):
                    if dp[col] < min1:
                        min2 = min1
                        min1 = dp[col]
                        min1_col = col
                    elif dp[col] < min2:
                        min2 = dp[col]

                new_dp7 = [0] * n
                for col in range(n):
                    if col != min1_col:
                        new_dp7[col] = grid[row][col] + min1
                    else:
                        new_dp7[col] = grid[row][col] + min2

                dp = new_dp7
                row -= 1

            # Unroll row 8
            if row >= 0:
                min1, min2 = float('inf'), float('inf')
                min1_col = -1
                for col in range(n):
                    if dp[col] < min1:
                        min2 = min1
                        min1 = dp[col]
                        min1_col = col
                    elif dp[col] < min2:
                        min2 = dp[col]

                new_dp8 = [0] * n
                for col in range(n):
                    if col != min1_col:
                        new_dp8[col] = grid[row][col] + min1
                    else:
                        new_dp8[col] = grid[row][col] + min2

                dp = new_dp8
                row -= 1

            # Unroll row 9
            if row >= 0:
                min1, min2 = float('inf'), float('inf')
                min1_col = -1
                for col in range(n):
                    if dp[col] < min1:
                        min2 = min1
                        min1 = dp[col]
                        min1_col = col
                    elif dp[col] < min2:
                        min2 = dp[col]

                new_dp9 = [0] * n
                for col in range(n):
                    if col != min1_col:
                        new_dp9[col] = grid[row][col] + min1
                    else:
                        new_dp9[col] = grid[row][col] + min2

                dp = new_dp9
                row -= 1

            # Unroll row 10 (final in this block)
            if row >= 0:
                min1, min2 = float('inf'), float('inf')
                min1_col = -1
                for col in range(n):
                    if dp[col] < min1:
                        min2 = min1
                        min1 = dp[col]
                        min1_col = col
                    elif dp[col] < min2:
                        min2 = dp[col]

                new_dp10 = [0] * n
                for col in range(n):
                    if col != min1_col:
                        new_dp10[col] = grid[row][col] + min1
                    else:
                        new_dp10[col] = grid[row][col] + min2

                dp = new_dp10
                row -= 1

        # Return the minimum value from the last updated dp
        min_falling_path_sum = float('inf')
        for val in dp:
            if val < min_falling_path_sum:
                min_falling_path_sum = val

        return min_falling_path_sum

20500