<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 {
    long long solve(vector<vector<int>>&matrix, int row, int col, int n,vector<vector<int>>&dp){
        if(col<0 || col>n-1 || row>n-1)  return 1e9;
        
        if(row==n-1 && col<n){
            return matrix[row][col];
        }


        if(dp[row][col]!=-1) return dp[row][col];


        long long leftdg=matrix[row][col]+solve(matrix,row+1,col-1,n,dp);
        long long down=matrix[row][col]+solve(matrix,row+1,col,n,dp);
        long long rightdg=matrix[row][col]+solve(matrix,row+1,col+1,n,dp);

        return dp[row][col]=min(leftdg,min(down,rightdg));
    }

    void tabulation(vector<vector<int>>matrix, vector<vector<int>>&dp){
         int n=matrix.size();

        //   start from the second last row of the matrix

        for(int i=n-2;i>=0;i--){
            for(int j=n-1;j>=0;j--){
                if(j==n-1){
                   int leftdg=matrix[i][j]+dp[i+1][j-1];
                   int down=matrix[i][j]+dp[i+1][j];
                   dp[i][j]=min(leftdg,down);
                }
                else if(j==0){
                   int rightdg=matrix[i][j]+dp[i+1][j+1];
                   int down=matrix[i][j]+dp[i+1][j];
                   dp[i][j]=min(rightdg,down);
                }
                else{
                   int rightdg=matrix[i][j]+dp[i+1][j+1];
                   int down=matrix[i][j]+dp[i+1][j];
                   int leftdg=matrix[i][j]+dp[i+1][j-1];
                   dp[i][j]=min(down,min(rightdg,leftdg));
                }
            }
        }
    }
public:
    int minFallingPathSum(vector<vector<int>>& matrix) {
        int n=matrix.size();

        if(n==1) return matrix[0][0];

        vector<vector<int>>dp(n,vector<int>(n,0));
        //  copy the last row into the dp table because its bottom up appraoch 
        for(int i=0;i<n;i++){
            dp[n-1][i]=matrix[n-1][i];
        }
        
        tabulation(matrix,dp);

        //  return min element in the first row of dp vector
        int ans=INT_MAX;
        for(int i=0;i<n;i++){
            if(dp[0][i]<ans){
                ans=dp[0][i];
            }
        }

        return ans;
    }
};
14500