Maximum Number of Points with Cost

medium dp prefix max

Problem

You are given an m × n grid points and you must pick exactly one cell from every row. Your score is the sum of the picked values, but consecutive rows charge a penalty: if you pick column c1 in one row and column c2 in the next, you pay |c1 − c2|. Return the maximum score you can finish with.

Inputpoints = [[1,2,3],[1,5,1],[3,1,1]]
Output9
Pick 3 (row 0, col 2), 5 (row 1, col 1), 3 (row 2, col 0): 11 points minus the column shifts |2−1| + |1−0| = 2 leaves 9.

def max_points(points):
    n = len(points[0])
    dp = points[0][:]
    for row in points[1:]:
        left = [0] * n
        right = [0] * n
        left[0] = dp[0]
        for j in range(1, n):
            left[j] = max(left[j - 1] - 1, dp[j])
        right[n - 1] = dp[n - 1]
        for j in range(n - 2, -1, -1):
            right[j] = max(right[j + 1] - 1, dp[j])
        dp = [row[j] + max(left[j], right[j]) for j in range(n)]
    return max(dp)
function maxPoints(points) {
  const n = points[0].length;
  let dp = points[0].slice();
  for (let r = 1; r < points.length; r++) {
    const left = new Array(n), right = new Array(n);
    left[0] = dp[0];
    for (let j = 1; j < n; j++) left[j] = Math.max(left[j - 1] - 1, dp[j]);
    right[n - 1] = dp[n - 1];
    for (let j = n - 2; j >= 0; j--) right[j] = Math.max(right[j + 1] - 1, dp[j]);
    dp = points[r].map((v, j) => v + Math.max(left[j], right[j]));
  }
  return Math.max(...dp);
}
long maxPoints(int[][] points) {
    int n = points[0].length;
    long[] dp = new long[n];
    for (int j = 0; j < n; j++) dp[j] = points[0][j];
    for (int r = 1; r < points.length; r++) {
        long[] left = new long[n], right = new long[n];
        left[0] = dp[0];
        for (int j = 1; j < n; j++) left[j] = Math.max(left[j - 1] - 1, dp[j]);
        right[n - 1] = dp[n - 1];
        for (int j = n - 2; j >= 0; j--) right[j] = Math.max(right[j + 1] - 1, dp[j]);
        for (int j = 0; j < n; j++) dp[j] = points[r][j] + Math.max(left[j], right[j]);
    }
    long best = dp[0];
    for (int j = 1; j < n; j++) best = Math.max(best, dp[j]);
    return best;
}
long long maxPoints(vector<vector<int>>& points) {
    int n = points[0].size();
    vector<long long> dp(points[0].begin(), points[0].end());
    for (int r = 1; r < (int)points.size(); r++) {
        vector<long long> left(n), right(n);
        left[0] = dp[0];
        for (int j = 1; j < n; j++) left[j] = max(left[j - 1] - 1, dp[j]);
        right[n - 1] = dp[n - 1];
        for (int j = n - 2; j >= 0; j--) right[j] = max(right[j + 1] - 1, dp[j]);
        for (int j = 0; j < n; j++) dp[j] = points[r][j] + max(left[j], right[j]);
    }
    return *max_element(dp.begin(), dp.end());
}
Time: O(m · n) Space: O(n)