Open In App

Maximizing sum of non-consecutive elements in Matrix

Given a matrix of N*3 where N is the number of rows, the task is to choose an integer value from each row in such a manner that the sum of all the values should be maximum and can’t choose the same column values from two consecutive rows.

Examples:



Input: n = 3
point[ ][ ]= 1 2 5
                  3 1 1
                  3 3 3 
Output: 11
Explanation: Choose 5 from first row, 3 from the second row and 3 from third row, maximum sum is 11.

Input: n = 3
point[ ][ ]= 10 40 70
                  20 50 80
                  30 60 90
Output: 210



Approach: To solve the problem follow the below idea:

The idea is to apply Dynamic Programming(Memoization) to solve this problem Recursively. We will recursively call all the subproblems and the result of these subproblems will store in an dp array of similar size(N*3) to decrease the redundant repeating calculations. The Base Case for this problem will be the last row so We will assign the last row values of dp array with the last row values of given N*3 array.

Below are the steps for the above approach:

Below is the code for the above approach:




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
int maximumPointsUtil(int index, int dp[],
                      vector<vector<int> >& points)
{
    if (dp[index] != -1)
        return dp[index];
    int row = index / 3;
    int col = index % 3;
    if (col == 0) {
        dp[index]
            = points[row][col]
              + max(
                    maximumPointsUtil(index + 4, dp, points),
                    maximumPointsUtil(index + 5, dp, points));
        return dp[index];
    }
    else if (col == 1) {
        dp[index]
            = points[row][col]
              + max(
                    maximumPointsUtil(index + 2, dp, points),
                    maximumPointsUtil(index + 4, dp, points));
        return dp[index];
    }
    else
    {
        dp[index]
            = points[row][col]
              + max(
                    maximumPointsUtil(index + 1, dp, points),
                    maximumPointsUtil(index + 2, dp, points));
        return dp[index];
    }
}
int maximumPoints(vector<vector<int> >& points, int n)
{
    int dp[n * 3];
    memset(dp, -1, sizeof(dp));
    dp[n * 3 - 1] = points[n - 1][2];
    dp[n * 3 - 2] = points[n - 1][1];
    dp[n * 3 - 3] = points[n - 1][0];
    int first = maximumPointsUtil(0, dp, points);
    int second = maximumPointsUtil(1, dp, points);
    int third = maximumPointsUtil(2, dp, points);
    return max(first, max(second, third));
}
 
// Drivers code
int main()
{
    vector<vector<int> > points
        = { { 1, 2, 5 }, { 3, 1, 1 }, { 3, 3, 3 } };
    int n = points.size();
 
    // Function Call
    cout << maximumPoints(points, n);
    return 0;
}




import java.util.Arrays;
import java.util.Vector;
 
class Main {
    public static int maximumPointsUtil(int index, int[] dp, Vector<Vector<Integer> > points)
    {
        if (dp[index] != -1)
            return dp[index];
 
        int row = index / 3;
        int col = index % 3;
 
        if (col == 0) {
            dp[index] = points.get(row).get(col)
                        + Math.max(maximumPointsUtil(index + 4, dp, points), maximumPointsUtil(index + 5, dp, points));
            return dp[index];
        }
        else if (col == 1) {
            dp[index] = points.get(row).get(col)
                        + Math.max(maximumPointsUtil(index + 2, dp, points), maximumPointsUtil(index + 4, dp, points));
            return dp[index];
        }
        else {
            dp[index] = points.get(row).get(col)
                        + Math.max(maximumPointsUtil(index + 1, dp, points), maximumPointsUtil(index + 2, dp, points));
            return dp[index];
        }
    }
 
    public static int maximumPoints(Vector<Vector<Integer> > points, int n)
    {
        int[] dp = new int[n * 3];
        Arrays.fill(dp, -1);
        dp[n * 3 - 1] = points.get(n - 1).get(2);
        dp[n * 3 - 2] = points.get(n - 1).get(1);
        dp[n * 3 - 3] = points.get(n - 1).get(0);
        int first = maximumPointsUtil(0, dp, points);
        int second = maximumPointsUtil(1, dp, points);
        int third = maximumPointsUtil(2, dp, points);
        return Math.max(first, Math.max(second, third));
    }
 
    public static void main(String[] args)
    {
        Vector<Vector<Integer> > points = new Vector<>();
        points.add(new Vector<>(Arrays.asList(1, 2, 5)));
        points.add(new Vector<>(Arrays.asList(3, 1, 1)));
        points.add(new Vector<>(Arrays.asList(3, 3, 3)));
 
        int n = points.size();
        System.out.println(maximumPoints(points, n));
    }
}
// THIS CODE IS CONTRIBUTED BY YASH AGARWAL(YASHAGARWAL2852002)




def maximumPointsUtil(index, dp, points):
    if dp[index] != -1:
        return dp[index]
    row = index // 3
    col = index % 3
    if col == 0:
        dp[index] = points[row][col] + max(maximumPointsUtil(index + 4, dp, points), maximumPointsUtil(index + 5, dp, points))
        return dp[index]
    elif col == 1:
        dp[index] = points[row][col] + max(maximumPointsUtil(index + 2, dp, points), maximumPointsUtil(index + 4, dp, points))
        return dp[index]
    else:
        dp[index] = points[row][col] + max(maximumPointsUtil(index + 1, dp, points), maximumPointsUtil(index + 2, dp, points))
        return dp[index]
 
def maximumPoints(points):
    n = len(points)
    dp = [-1] * (n * 3)
    dp[n * 3-1] = points[n-1][2]
    dp[n * 3-2] = points[n-1][1]
    dp[n * 3-3] = points[n-1][0]
    first = maximumPointsUtil(0, dp, points)
    second = maximumPointsUtil(1, dp, points)
    third = maximumPointsUtil(2, dp, points)
    return max(first, max(second, third))
 
points = [[1, 2, 5],
          [3, 1, 1],
          [3, 3, 3]]
print(maximumPoints(points))
# THIS CODE IS CONTRIBUTED BY YASH AGARWAL(YASHAGARWAL2852002)




using System;
using System.Collections.Generic;
 
public class Program {
    static int MaximumPointsUtil(int index, int[] dp, List<List<int> > points)
    {
        if (dp[index] != -1)
            return dp[index];
        int row = index / 3;
        int col = index % 3;
        if (col == 0) {
            dp[index] = points[row][col] + Math.Max(MaximumPointsUtil(index + 4, dp, points), MaximumPointsUtil(index + 5, dp, points));
            return dp[index];
        }
        else if (col == 1) {
            dp[index] = points[row][col] + Math.Max(MaximumPointsUtil(index + 2, dp, points), MaximumPointsUtil(index + 4, dp, points));
            return dp[index];
        }
        else {
            dp[index] = points[row][col] + Math.Max(MaximumPointsUtil(index + 1, dp, points), MaximumPointsUtil(index + 2, dp, points));
            return dp[index];
        }
    }
 
    static int MaximumPoints(List<List<int> > points, int n)
    {
        int[] dp = new int[n * 3];
        Array.Fill(dp, -1);
        dp[n * 3 - 1] = points[n - 1][2];
        dp[n * 3 - 2] = points[n - 1][1];
        dp[n * 3 - 3] = points[n - 1][0];
        int first = MaximumPointsUtil(0, dp, points);
        int second = MaximumPointsUtil(1, dp, points);
        int third = MaximumPointsUtil(2, dp, points);
        return Math.Max(first, Math.Max(second, third));
    }
 
    public static void Main()
    {
        List<List<int> > points = new List<List<int> >{
            new List<int>{ 1, 2, 5 },
            new List<int>{ 3, 1, 1 },
            new List<int>{ 3, 3, 3 }
        };
        int n = points.Count;
        Console.WriteLine(MaximumPoints(points, n));
    }
}
// THIS CODE IS CONTRIBUTED BY YASH AGARWAL(YASHAGARWAL2852002)




function maximumPointsUtil(index, dp, points) {
  if(dp[index] !== -1) return dp[index];
  const row = Math.floor(index / 3);
  const col = index % 3;
  if(col === 0) {
    dp[index] = points[row][col] + Math.max(maximumPointsUtil(index+4, dp, points), maximumPointsUtil(index+5, dp, points));
    return dp[index];
  }
  else if(col === 1) {
    dp[index] = points[row][col] + Math.max(maximumPointsUtil(index+2, dp, points), maximumPointsUtil(index+4, dp, points));
    return dp[index];
  }
  else {
    dp[index] = points[row][col] + Math.max(maximumPointsUtil(index+1, dp, points), maximumPointsUtil(index+2, dp, points));
    return dp[index];
  }
}
 
function maximumPoints(points, n) {
  const dp = new Array(n*3).fill(-1);
  dp[n*3-1] = points[n-1][2];
  dp[n*3-2] = points[n-1][1];
  dp[n*3-3] = points[n-1][0];
  const first = maximumPointsUtil(0, dp, points);
  const second = maximumPointsUtil(1, dp, points);
  const third = maximumPointsUtil(2, dp, points);
  return Math.max(first, Math.max(second, third));
}
 
const points = [[1, 2, 5], [3, 1, 1], [3, 3, 3]];
const n = points.length;
console.log(maximumPoints(points, n));
// THIS CODE IS CONTRIBUTED BY YASH AGARWAL(YASHAGARWAL2852002)

Output
11










Time Complexity: O(3n), where n is the number of rows/days.
Auxiliary Space: O(3n)

Efficient approach : Using DP Tabulation method ( Iterative approach )

The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.

Steps to solve this problem :

Implementation :




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
int maximumPoints(vector<vector<int>>& points) {
    int n = points.size();
    vector<vector<int>> dp(n, vector<int>(3, 0));
 
    // Initialize the DP table with the last row values
    dp[n - 1][0] = points[n - 1][0];
    dp[n - 1][1] = points[n - 1][1];
    dp[n - 1][2] = points[n - 1][2];
 
    // Fill the DP table from the second last row to the first row
    for (int row = n - 2; row >= 0; row--) {
        for (int col = 0; col < 3; col++) {
            // Calculate the maximum points for the current cell based on the adjacent cells
            if (col == 0) {
                dp[row][col] = points[row][col] + max(dp[row + 1][col + 1], dp[row + 1][col + 2]);
            } else if (col == 1) {
                dp[row][col] = points[row][col] + max(dp[row + 1][col - 1], dp[row + 1][col + 1]);
            } else {
                dp[row][col] = points[row][col] + max(dp[row + 1][col - 1], dp[row + 1][col - 2]);
            }
        }
    }
 
    // Find the maximum points in the first row
    return max(dp[0][0], max(dp[0][1], dp[0][2]));
}
 
// Driver Code
int main() {
    vector<vector<int>> points = { { 1, 2, 5 }, { 3, 1, 1 }, { 3, 3, 3 } };
    int result = maximumPoints(points);
 
    cout << result << endl;
    return 0;
}




import java.util.Arrays;
 
public class MaximumPoints {
 
    public static int maximumPoints(int[][] points) {
        int n = points.length;
        int[][] dp = new int[n][3];
 
        // Initialize the DP table with the last row values
        dp[n - 1][0] = points[n - 1][0];
        dp[n - 1][1] = points[n - 1][1];
        dp[n - 1][2] = points[n - 1][2];
 
        // Fill the DP table from the second last row to the first row
        for (int row = n - 2; row >= 0; row--) {
            for (int col = 0; col < 3; col++) {
                // Calculate the maximum points for the current cell based on the adjacent cells
                if (col == 0) {
                    dp[row][col] = points[row][col] + Math.max(dp[row + 1][col + 1], dp[row + 1][col + 2]);
                } else if (col == 1) {
                    dp[row][col] = points[row][col] + Math.max(dp[row + 1][col - 1], dp[row + 1][col + 1]);
                } else {
                    dp[row][col] = points[row][col] + Math.max(dp[row + 1][col - 1], dp[row + 1][col - 2]);
                }
            }
        }
 
        // Find the maximum points in the first row
        return Math.max(dp[0][0], Math.max(dp[0][1], dp[0][2]));
    }
 
    // Driver Code
    public static void main(String[] args) {
        int[][] points = { { 1, 2, 5 }, { 3, 1, 1 }, { 3, 3, 3 } };
        int result = maximumPoints(points);
 
        System.out.println(result);
    }
}




def maximumPoints(points):
    n = len(points)
     
    # Initialize the DP table with the last row values
    dp = [[0] * 3 for _ in range(n)]
    dp[n - 1][0] = points[n - 1][0]
    dp[n - 1][1] = points[n - 1][1]
    dp[n - 1][2] = points[n - 1][2]
 
    # Fill the DP table from the second last row to the first row
    for row in range(n - 2, -1, -1):
        for col in range(3):
            # Calculate the maximum points for the current cell based on the adjacent cells
            if col == 0:
                dp[row][col] = points[row][col] + max(dp[row + 1][col + 1], dp[row + 1][col + 2])
            elif col == 1:
                dp[row][col] = points[row][col] + max(dp[row + 1][col - 1], dp[row + 1][col + 1])
            else:
                dp[row][col] = points[row][col] + max(dp[row + 1][col - 1], dp[row + 1][col - 2])
 
    # Find the maximum points in the first row
    return max(dp[0][0], max(dp[0][1], dp[0][2]))
 
# Driver Code
if __name__ == "__main__":
    points = [[1, 2, 5], [3, 1, 1], [3, 3, 3]]
    result = maximumPoints(points)
 
    print(result)




using System;
using System.Collections.Generic;
 
class GFG
{
    static int MaximumPoints(List<List<int>> points)
    {
        int n = points.Count;
        int[][] dp = new int[n][];
        for (int i = 0; i < n; i++)
        {
            dp[i] = new int[3];
        }
 
        // Initialize the DP table with the last row values
        dp[n - 1][0] = points[n - 1][0];
        dp[n - 1][1] = points[n - 1][1];
        dp[n - 1][2] = points[n - 1][2];
 
        // Fill the DP table from the second last row to the first row
        for (int row = n - 2; row >= 0; row--)
        {
            for (int col = 0; col < 3; col++)
            {
                // Calculate the maximum points for the current cell based on the adjacent cells
                if (col == 0)
                {
                    dp[row][col] = points[row][col] + Math.Max(dp[row + 1][col + 1],
                                                               dp[row + 1][col + 2]);
                }
                else if (col == 1)
                {
                    dp[row][col] = points[row][col] + Math.Max(dp[row + 1][col - 1],
                                                               dp[row + 1][col + 1]);
                }
                else
                {
                    dp[row][col] = points[row][col] + Math.Max(dp[row + 1][col - 1],
                                                               dp[row + 1][col - 2]);
                }
            }
        }
 
        // Find the maximum points in the first row
        return Math.Max(dp[0][0], Math.Max(dp[0][1], dp[0][2]));
    }
 
    static void Main(string[] args)
    {
        List<List<int>> points = new List<List<int>>
        {
            new List<int> { 1, 2, 5 },
            new List<int> { 3, 1, 1 },
            new List<int> { 3, 3, 3 }
        };
 
        int result = MaximumPoints(points);
 
        Console.WriteLine(result);
    }
}




function maximumPoints(points) {
    let n = points.length;
    let dp = new Array(n).fill(0).map(() => new Array(3).fill(0));
 
    // Initialize the DP table with the last row values
    dp[n - 1][0] = points[n - 1][0];
    dp[n - 1][1] = points[n - 1][1];
    dp[n - 1][2] = points[n - 1][2];
 
    // Fill the DP table from the second last row to the first row
    for (let row = n - 2; row >= 0; row--) {
        for (let col = 0; col < 3; col++) {
            // Calculate the maximum points for the current cell based on the adjacent cells
            if (col === 0) {
                dp[row][col] = points[row][col] + Math.max(dp[row + 1][col + 1], dp[row + 1][col + 2]);
            } else if (col === 1) {
                dp[row][col] = points[row][col] + Math.max(dp[row + 1][col - 1], dp[row + 1][col + 1]);
            } else {
                dp[row][col] = points[row][col] + Math.max(dp[row + 1][col - 1], dp[row + 1][col - 2]);
            }
        }
    }
 
    // Find the maximum points in the first row
    return Math.max(dp[0][0], Math.max(dp[0][1], dp[0][2]));
}
 
// Driver Code
let points = [[1, 2, 5], [3, 1, 1], [3, 3, 3]];
let result = maximumPoints(points);
 
console.log(result);

Output:

11

Time Complexity: O(3n), where n is the number of rows/days.

Auxiliary Space: O(3n)


Article Tags :