<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:
    def maxPoints(self, points: List[List[int]]) -> int:
        # mem = [[-math.inf for i in range(len(points[0]))] for j in range(len(points))]
        #ans = self.maxPointsUtil(0, points, -1, mem)
        ans = self.maxPointsDP(points)
        return ans
    
    def maxPointsUtil(self, row, points, prev, mem):
        if row >= len(points):
            return 0
        if mem[row][prev] !=-math.inf:
            return mem[row][prev]
        ans = -math.inf
        currmax = 0
        for i in range(len(points[row])):
            if prev == -1:
                currmax = points[row][i] + self.maxPointsUtil(row+1, points, i, mem)
            else:
                currmax = points[row][i] - abs(i-prev) + self.maxPointsUtil(row+1, points, i, mem)
            ans = max(ans, currmax)
        mem[row][prev] = ans
        return ans

    
    def maxPointsDP(self, points):
        prevRow = 0
        for i in range(1, len(points)):
            left = [0 for i in range(len(points[i]))]
            right = [0 for i in range(len(points[i]))]
            for j in range(len(points[i])):
                if j == 0:
                    left[j] = points[prevRow][j]
                else:
                    left[j] = max(left[j-1]-1, points[prevRow][j])
            for j in range(len(points[i])-1, -1, -1):
                if j == len(points[i])-1:
                    right[j] = points[prevRow][j]
                else:
                    right[j] = max(right[j+1]-1, points[prevRow][j]) 
                points[i][j] = max(left[j], right[j])+points[i][j]
            prevRow = i
        
        ans = points[len(points)-1][0]
        for j in range(len(points[len(points)-1])):
            ans = max(ans, points[len(points)-1][j])
        return ans

            
            

        
                

# [1, 2, 3]

# left direction
# [1, 2, ]


# [1, 5, 1]
# [3, 1, 1]

# [2,7,3]

# left [2, 7, 6]
# right[6, 7, 3]
# right
# [1,2,3]
# [1,2,1]
# [4,5,1]

# [1,2,3]
# [2,7,3]
# [9,8,7]

# 1 -> [1,4,0]
# 2-> [0,5,0] ->  [(1,1)] -> [(2,2)]
# 3 -> [0,4,1]


# 1 2 3
# 3 2 1
# 1 2 3

# [(0,0), (0,1), (0,2)] -> [(1,0),(1,1),(1,2)] -> 
51500