<p>You are given an <code>m x n</code> integer matrix <code>points</code> (<strong>0-indexed</strong>). Starting with <code>0</code> points, you want to <strong>maximize</strong> the number of points you can get from the matrix.</p>

<p>To gain points, you must pick one cell in <strong>each row</strong>. Picking the cell at coordinates <code>(r, c)</code> will <strong>add</strong> <code>points[r][c]</code> to your score.</p>

<p>However, you will lose points if you pick a cell too far from the cell that you picked in the previous row. For every two adjacent rows <code>r</code> and <code>r + 1</code> (where <code>0 &lt;= r &lt; m - 1</code>), picking cells at coordinates <code>(r, c<sub>1</sub>)</code> and <code>(r + 1, c<sub>2</sub>)</code> will <strong>subtract</strong> <code>abs(c<sub>1</sub> - c<sub>2</sub>)</code> from your score.</p>

<p>Return <em>the <strong>maximum</strong> number of points you can achieve</em>.</p>

<p><code>abs(x)</code> is defined as:</p>

<ul>
	<li><code>x</code> for <code>x &gt;= 0</code>.</li>
	<li><code>-x</code> for <code>x &lt; 0</code>.</li>
</ul>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong><strong> </strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/07/12/screenshot-2021-07-12-at-13-40-26-diagram-drawio-diagrams-net.png" style="width: 300px; height: 300px;" />
<pre>
<strong>Input:</strong> points = [[1,2,3],[1,5,1],[3,1,1]]
<strong>Output:</strong> 9
<strong>Explanation:</strong>
The blue cells denote the optimal cells to pick, which have coordinates (0, 2), (1, 1), and (2, 0).
You add 3 + 5 + 3 = 11 to your score.
However, you must subtract abs(2 - 1) + abs(1 - 0) = 2 from your score.
Your final score is 11 - 2 = 9.
</pre>

<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/07/12/screenshot-2021-07-12-at-13-42-14-diagram-drawio-diagrams-net.png" style="width: 200px; height: 299px;" />
<pre>
<strong>Input:</strong> points = [[1,5],[2,3],[4,2]]
<strong>Output:</strong> 11
<strong>Explanation:</strong>
The blue cells denote the optimal cells to pick, which have coordinates (0, 1), (1, 1), and (2, 0).
You add 5 + 3 + 4 = 12 to your score.
However, you must subtract abs(1 - 1) + abs(1 - 0) = 1 from your score.
Your final score is 12 - 1 = 11.
</pre>

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

<ul>
	<li><code>m == points.length</code></li>
	<li><code>n == points[r].length</code></li>
	<li><code>1 &lt;= m, n &lt;= 10<sup>5</sup></code></li>
	<li><code>1 &lt;= m * n &lt;= 10<sup>5</sup></code></li>
	<li><code>0 &lt;= points[r][c] &lt;= 10<sup>5</sup></code></li>
</ul>

class Solution {
    // MEMOIZATION

    // long long f(int row, int col, vector<vector<int>>& points, int n, int m, vector<vector<long long>> &dp){
    //     if(row==n){
    //         return 0;
    //     }

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

    //     long long pts = points[row][col];

    //     long long ans = pts;
    //     for(int i=0; i<m; i++){
    //         ans = max(ans,pts+f(row+1, i, points, n, m, dp) - abs(i-col));
    //     }

    //     return dp[row][col]=ans;
    // }
public:
    // long long maxPoints(vector<vector<int>>& points) {
    // //     long long ans = 0;
    // //     int n = points.size();
    // //     int m = points[0].size();

    // //     vector<vector<long long>> dp(n, vector<long long>(m, -1));

    // //     for(int i=0; i<m; i++){
    // //         ans=max(ans, f(0, i, points, n, m, dp));
    // //     }

    // //     return ans;
    // // }


    // // TABULATION 

    // long long maxPoints(vector<vector<int>>& points) {
    //     long long ans = 0;
    //     int n = points.size();
    //     int m = points[0].size();

    //     vector<vector<long long>> dp(n+1, vector<long long>(m+1, 0));

    //     for(int i=n-1; i>=0; i--){ //row
    //         for(int j=m-1; j>=0; j--){ //col
    //             long long pts = points[i][j];
    //             long long temp = pts;
    //             for(int k=0; k<m; k++){ // i
    //                 temp = max(temp, pts+dp[i+1][k] - abs(k-j));
    //             }
    //             dp[i][j]=temp;
    //         }
    //     }

    //     for(int i=0; i<m; i++){
    //         ans=max(ans, dp[0][i]);
    //     }

    //     return ans;
    // }


    // optimized tabulation to remove TLE

    long long maxPoints(vector<vector<int>>& points) {
        int n = points.size();
        int m = points[0].size();

        vector<vector<long long>> dp(n+1, vector<long long>(m+1, 0));
        vector<long long> leftmax(m+1, 0);
        vector<long long> rightmax(m+1, 0);
        for(int row=n-1; row>=0; row--){
            leftmax[0]=dp[row+1][0];
            for(int col=1; col<m; col++){
                leftmax[col]= max(dp[row+1][col], leftmax[col-1]-1);
            }

            rightmax[m-1]=dp[row+1][m-1];
            for(int col=m-2; col>=0; col--){
                rightmax[col]=max(dp[row+1][col], rightmax[col+1]-1);
            }

            for(int col=0; col<m; col++){
                dp[row][col]= max(leftmax[col], rightmax[col])+points[row][col];
            }
        }

        long long ans = 0;
        for(int i=0; i<m ; i++){
            ans=max(ans , dp[0][i]);
        }
        return ans;

    }
};
109293