Maximum Number of Points with Cost

Updated on 16 June, 2025
Maximum Number of Points with Cost header image

Problem Statement

In this challenge, you are presented with a two-dimensional integer matrix named points, indexed from 0. The matrix dimension is m x n, where m is the number of rows and n is the number of columns. Starting with a score of zero, your goal is to maximize the score by selecting one cell from each row.

When you choose a cell (r, c) in the matrix, the value points[r][c] is added to your score. However, there's a catch: if the positions of the cells chosen in consecutive rows are too far apart horizontally, you incur a penalty. This penalty is calculated as the absolute difference between the column indices of the selected cells from two consecutive rows. Your task is to determine the maximum score possible after considering all additions and subtractions.

Examples

Example 1

Input:

points = [[1,2,3],[1,5,1],[3,1,1]]

Output:

9

Explanation:

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.

Example 2

Input:

points = [[1,5],[2,3],[4,2]]

Output:

11

Explanation:

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.

Constraints

  • m == points.length
  • n == points[r].length
  • 1 <= m, n <= 105
  • 1 <= m * n <= 105
  • 0 <= points[r][c] <= 105

Approach and Intuition

Let's dissect the problem with the assistance of the provided examples and the stated constraints:

Understanding the Dynamics with Examples

  1. In Example 1:

    • Input matrix: [[1,2,3],[1,5,1],[3,1,1]]
    • The optimal path starts at the cell (0, 2) then goes to (1, 1) and ends at (2, 0).
    • Total points collected: 3 (from points[0][2]) + 5 (from points[1][1]) + 3 (from points[2][0]) = 11
    • The penalty incurred: abs(2-1) + abs(1-0) = 2 from moving between selected cells.
    • Final score: 11 - 2 = 9

    This demonstrates the need to balance between choosing high-value cells and minimizing the movement penalty between consecutive rows.

  2. In Example 2:

    • Input matrix: [[1,5],[2,3],[4,2]]
    • The optimal path starts at the cell (0, 1) then goes to (1, 1), and ends at (2, 0).
    • Total collected points: 5 + 3 + 4 = 12
    • The penalty incurred: abs(1-1) + abs(1-0) = 1
    • Final score: 12 - 1 = 11

From these examples, we observe the following:

  • Structural Understanding: The problem is inherently dynamic, where the optimum choice at each step relies on previous decisions.
  • Dynamic Programming Strategy: Modeling this problem with a dynamic programming approach seems crucial. For every row r, and every possible column selection c, maintain the maximum possible score up to that point. Transition between states would consider all possible previous column choices c' from row r-1, maximizing points[r][c] - abs(c - c') + dp[r-1][c'].
  • Initialization and Iteration: The first row serves as the base case where no penalty applies, and subsequent rows build upon previous computations.
  • Efficient Computation and Pruning: Given the large size of m and n (up to 105), optimizing the dynamic transitions and reducing redundant calculations is significant. Strategies like maintaining maximum and second maximum values from the previous row could be explored to reduce the time complexity per row transition.

In essence, understanding the penalty mechanism and designing an efficient state transition strategy are central to solving this problem optimally within given constraints.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    long long maxScore(vector<vector<int>>& matrix) {
        int nCols = matrix[0].size();
        vector<long long> prevRow(nCols);

        for (auto& row : matrix) {
            long long maxLeft = 0;

            // Traverse from left to right
            for (int j = 0; j < nCols; ++j) {
                maxLeft = max(maxLeft - 1, prevRow[j]);
                prevRow[j] = maxLeft;
            }

            long long maxRight = 0;
            // Traverse from right to left
            for (int j = nCols - 1; j >= 0; --j) {
                maxRight = max(maxRight - 1, prevRow[j]);
                prevRow[j] = max(prevRow[j], maxRight) + row[j];
            }
        }

        // Extract the maximum score
        long long highestScore = 0;
        for (int j = 0; j < nCols; ++j) {
            highestScore = max(highestScore, prevRow[j]);
        }

        return highestScore;
    }
};

Solve the maximum number of points with cost problem by implementing the maxScore function in C++. Begin by determining the number of columns in the matrix using int nCols = matrix[0].size();. Initialize a vector prevRow to store intermediate results.

  • Traverse each row in the matrix, updating prevRow with the accumulated maximum scores from the left and right directions to account for the cost constraints when moving to different columns.
  • For the left-to-right pass, use the local maximum maxLeft to update the values in prevRow.
  • For the right-to-left pass, incorporate another local maximum maxRight to combine the results with those from the leftward pass, adding the current row values for the updated scores.
  • After processing all rows, determine the final maximum score by iterating through prevRow and finding the highest value.

Return the highest score as the output of the function to represent the maximum score attainable from the matrix configuration, considering all cost-impact movements between rows and columns. This approach ensures that every cell is evaluated for optimal paths from both directions, effectively accounting for the problem's constraints.

java
class Solution {

    public long maximumPoints(int[][] grid) {
        int width = grid[0].length;
        long[] priorRow = new long[width];

        for (int[] currentRow : grid) {
            // Store the maximum findable value from previous iterations
            long maxCarry = 0;

            // Process from left to right
            for (int i = 0; i < width; ++i) {
                maxCarry = Math.max(maxCarry - 1, priorRow[i]);
                priorRow[i] = maxCarry;
            }

            maxCarry = 0;
            // Process from right to left
            for (int i = width - 1; i >= 0; --i) {
                maxCarry = Math.max(maxCarry - 1, priorRow[i]);
                priorRow[i] = Math.max(priorRow[i], maxCarry) + currentRow[i];
            }
        }

        // Determine the highest points obtainable in the last computed row
        long totalMaxPoints = 0;
        for (long point : priorRow) {
            totalMaxPoints = Math.max(totalMaxPoints, point);
        }

        return totalMaxPoints;
    }
}

The Java solution provided solves the problem of finding the maximum number of points you can obtain from a grid, where moving horizontally costs you points. The method maximumPoints internally computes the solution utilizing a dynamic programming approach and optimizations for efficient horizontal traversal handling.

  • Initialize a priorRow array with the same width as the grid to keep track of the maximum points that can be obtained up to each position.
  • Loop through each row of the grid and update the priorRow in two passes:
    1. Left to Right Pass: Update priorRow values by considering the maximum point value that can be carried from the left side minus the cost of moving to the right. This pass ensures that the points from the left are considered.
    2. Right to Left Pass: Similar to the first pass but from the right to the left. This pass makes sure that points from the right are maximized after considering points from the left, storing the best possible value plus the grid value itself.
  • Once all rows are processed, the final maximum points which can be obtained are determined by considering the maximum value in the priorRow after processing all rows.

Execute the example provided to integrate this strategy into broader applications where computing optimized paths or scores from 2D matrices is required, especially under constraints that mimic movement penalties.

python
class Solution:
    def calculateMaxPoints(self, grid: List[List[int]]) -> int:
        column_count = len(grid[0])
        last_row_scores = [0] * column_count

        for grid_row in grid:
            max_from_left = 0

            # Left to right calculation
            for idx in range(column_count):
                max_from_left = max(max_from_left - 1, last_row_scores[idx])
                last_row_scores[idx] = max_from_left

            max_from_right = 0
            # Right to left calculation
            for idx in range(column_count - 1, -1, -1):
                max_from_right = max(max_from_right - 1, last_row_scores[idx])
                last_row_scores[idx] = (
                    max(last_row_scores[idx], max_from_right) + grid_row[idx]
                )

        # Maximum points in the finalized row
        return max(last_row_scores)

This Python solution tackles the problem of finding the maximum points achievable on a m x n grid, each cell containing a point value. At each position, you may choose points based on the cost from moving horizontally across any number of cells. The primary mechanism involves dynamic programming to optimize the results through the rows processing both from left-to-right and right-to-left.

  • Initialize a column_count to the number of columns in the grid.
  • Prepare an array last_row_scores initialized to zero, with the length equal to column_count, to keep track of the maximum points obtainable until the current row.
  • Use a for-loop to traverse each row (grid_row) in the grid:
    • Initialize max_from_left to zero and iterate through indices from left to right. For each column, compare and update max_from_left with the existing maximum reduced by one or the score from last_row_scores at that column. Store the result back into last_row_scores.
    • After the left to right pass, initialize max_from_right to zero and iterate through indices from right to left. Update max_from_right in a similar method and adjust last_row_scores at each index by adding the current grid value at that index. This step combines both directions' calculations to provide the optimal path value for each cell in a row.
  • After processing all rows, the final maximum points obtainable is the maximum value from last_row_scores.

Execute the final line of code to return the maximum score from last_row_scores. This implementation ensures each cell's maximum achievable score is computed considering the penalties from horizontal movements both from previous and next columns. By efficiently combining both left and right movements, the solution dynamically updates the potential maximum values row by row, leading to the optimal solution.

Comments

No comments yet.