Open In App

Maximizing Merit Points in Training Program

Last Updated : 04 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Geek is going for n days training program, he can perform any one of these three activities Running, Fighting, and Learning Practice. Each activity has some point on each day. As Geek wants to improve all his skills, he can’t do the same activity on two consecutive days, so help Geek to maximize his merit points as we were given a 2D array of n*3 points corresponding to each day and activity.

Examples:

Input: n = 3, point[] = [[1, 2, 5], [3, 1, 1], [3, 3, 3]]
Output: 11
Explanation: Geek will learn a new move and earn 5 point then on second day he will do running and earn 3 point and on third day he will do fighting and earn 3 points so, maximum point is 11.

Approach: This can be solved with the following idea:

Using Dynamic Programming + Recursion, we can calculate the maximum points that we can get from choosing best activity for every index from given 3 activity.

Steps involved in the implementation of code:

  • Choose the best activity at the current index with respect to the last activity.
  • Base case if we are done with all day’s activity return 0.
  • start with -1 or 0 as the last activity.
  • Let 1 2 3 be the activity that we can do.
  • If have done 1 as last then try to maximize through 2 and 3 activities at the current index.
  • Store all possibilities and return the maximum that we can get.

Below is the implementation of the above approach :

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
 
// dp to store all possible state answers.
int dp[100001][4];
int sub(vector<vector<int> >& points, int last, int index)
{
    // Just return if u have done with all work.
    if (index == points.size())
        return 0;
 
    // if u have previously explore the state
    // give the most optimal answer.
    if (dp[index][last] != -1)
        return dp[index][last];
 
    // Store the most optimal answer for current
    // index and last activity.
    int ans = 0;
 
    // if this the first activity
    if (last == 0) {
        ans = max(ans,
                  max({ points[index][0]
                            + sub(points, 1, index + 1),
                        points[index][1]
                            + sub(points, 2, index + 1),
                        points[index][2]
                            + sub(points, 3, index + 1) }));
    }
 
    // if we have select first
    // activity in last try.
    else if (last == 1) {
        ans = max(ans,
                  max(points[index][1]
                          + sub(points, 2, index + 1),
                      points[index][2]
                          + sub(points, 3, index + 1)));
    }
 
    // if we have select second
    // activity in last try.
    else if (last == 2) {
        ans = max(ans,
                  max(points[index][0]
                          + sub(points, 1, index + 1),
                      points[index][2]
                          + sub(points, 3, index + 1)));
    }
 
    // if we have select thired activity
    // in last try.
    else {
        ans = max(ans,
                  max(points[index][1]
                          + sub(points, 2, index + 1),
                      points[index][0]
                          + sub(points, 1, index + 1)));
    }
 
    // Save the maximum possible points that we
    // can get on this index with this
    // last activity.
    return dp[index][last] = ans;
}
 
// Drivers code
int main()
{
    int n = 3;
    vector<vector<int> > points{ { 1, 2, 5 },
                                 { 3, 1, 1 },
                                 { 3, 3, 3 } };
 
    // inti all state of dp with -1.
    memset(dp, -1, sizeof(dp));
 
    // Function Call
    cout << "Maximum Points We Can Make : "
         << sub(points, 0, 0) << endl;
    return 0;
}


Java




// Java code for the above approach
 
import java.util.Arrays;
 
class GFG {
    // dp to store all possible state answers.
    static int[][] dp;
 
    static int sub(int[][] points, int last, int index)
    {
        // Just return if u have done with all work.
        if (index == points.length)
            return 0;
 
        // if u have previously explored the state
        // give the most optimal answer.
        if (dp[index][last] != -1)
            return dp[index][last];
 
        // Store the most optimal answer for the current
        // index and last activity.
        int ans = 0;
 
        // if this is the first activity
        if (last == 0) {
            ans = Math.max(
                ans,
                Math.max(
                    points[index][0]
                        + sub(points, 1, index + 1),
                    Math.max(
                        points[index][1]
                            + sub(points, 2, index + 1),
                        points[index][2]
                            + sub(points, 3, index + 1))));
        }
 
        // if we have selected the first
        // activity in the last try.
        else if (last == 1) {
            ans = Math.max(
                ans,
                Math.max(points[index][1]
                             + sub(points, 2, index + 1),
                         points[index][2]
                             + sub(points, 3, index + 1)));
        }
 
        // if we have selected the second
        // activity in the last try.
        else if (last == 2) {
            ans = Math.max(
                ans,
                Math.max(points[index][0]
                             + sub(points, 1, index + 1),
                         points[index][2]
                             + sub(points, 3, index + 1)));
        }
 
        // if we have selected the third activity
        // in the last try.
        else {
            ans = Math.max(
                ans,
                Math.max(points[index][1]
                             + sub(points, 2, index + 1),
                         points[index][0]
                             + sub(points, 1, index + 1)));
        }
 
        // Save the maximum possible points that we
        // can get on this index with this
        // last activity.
        return dp[index][last] = ans;
    }
 
    // Drivers code
    public static void main(String[] args)
    {
        int n = 3;
        int[][] points
            = { { 1, 2, 5 }, { 3, 1, 1 }, { 3, 3, 3 } };
 
        // init all state of dp with -1.
        dp = new int[points.length][4];
        for (int i = 0; i < points.length; i++) {
            Arrays.fill(dp[i], -1);
        }
 
        // Function Call
        System.out.println("Maximum Points We Can Make : "
                           + sub(points, 0, 0));
    }
}
 
// This code is contributed by Abhinav Mahajan (abhinav_m22)


Python3




# Function to calculate the maximum points
def sub(points, last, index, dp):
    # Return if all work is done
    if index == len(points):
        return 0
 
    # If state has been explored previously, return the answer
    if dp[index][last] != -1:
        return dp[index][last]
 
    # Store the optimal answer for the current index and last activity
    ans = 0
 
    # If this is the first activity
    if last == 0:
        ans = max(
            ans,
            max(
                points[index][0] + sub(points, 1, index + 1, dp),
                points[index][1] + sub(points, 2, index + 1, dp),
                points[index][2] + sub(points, 3, index + 1, dp),
            ),
        )
 
    # If the first activity was selected last time
    elif last == 1:
        ans = max(
            ans,
            max(
                points[index][1] + sub(points, 2, index + 1, dp),
                points[index][2] + sub(points, 3, index + 1, dp),
            ),
        )
 
    # If the second activity was selected last time
    elif last == 2:
        ans = max(
            ans,
            max(
                points[index][0] + sub(points, 1, index + 1, dp),
                points[index][2] + sub(points, 3, index + 1, dp),
            ),
        )
 
    # If the third activity was selected last time
    else:
        ans = max(
            ans,
            max(
                points[index][1] + sub(points, 2, index + 1, dp),
                points[index][0] + sub(points, 1, index + 1, dp),
            ),
        )
 
    # Save the maximum possible points for this index with this last activity
    dp[index][last] = ans
    return ans
 
 
# Driver code
if __name__ == "__main__":
    n = 3
    points = [[1, 2, 5], [3, 1, 1], [3, 3, 3]]
 
    # Initialize all states of dp with -1
    dp = [[-1 for _ in range(4)] for _ in range(len(points))]
 
    # Function Call
    print("Maximum Points We Can Make:", sub(points, 0, 0, dp))


C#




using System;
 
class Program {
    // dp to store all possible state answers.
    static int[, ] dp = new int[100001, 4];
 
    static int Sub(int[, ] points, int last, int index)
    {
        // Just return if u have done with all work.
        if (index == points.GetLength(0))
            return 0;
 
        // if u have previously explored the state
        // give the most optimal answer.
        if (dp[index, last] != -1)
            return dp[index, last];
 
        // Store the most optimal answer for the current
        // index and last activity.
        int ans = 0;
 
        // if this is the first activity
        if (last == 0) {
            ans = Math.Max(
                ans,
                Math.Max(
                    points[index, 0]
                        + Sub(points, 1, index + 1),
                    Math.Max(
                        points[index, 1]
                            + Sub(points, 2, index + 1),
                        points[index, 2]
                            + Sub(points, 3, index + 1))));
        }
 
        // if we have selected the first
        // activity in the last try.
        else if (last == 1) {
            ans = Math.Max(
                ans,
                Math.Max(points[index, 1]
                             + Sub(points, 2, index + 1),
                         points[index, 2]
                             + Sub(points, 3, index + 1)));
        }
 
        // if we have selected the second
        // activity in the last try.
        else if (last == 2) {
            ans = Math.Max(
                ans,
                Math.Max(points[index, 0]
                             + Sub(points, 1, index + 1),
                         points[index, 2]
                             + Sub(points, 3, index + 1)));
        }
 
        // if we have selected the third activity
        // in the last try.
        else {
            ans = Math.Max(
                ans,
                Math.Max(points[index, 1]
                             + Sub(points, 2, index + 1),
                         points[index, 0]
                             + Sub(points, 1, index + 1)));
        }
 
        // Save the maximum possible points that we
        // can get on this index with this
        // last activity.
        return dp[index, last] = ans;
    }
 
    // Driver code
    static void Main()
    {
        int[, ] points
            = { { 1, 2, 5 }, { 3, 1, 1 }, { 3, 3, 3 } };
 
        // initialize all states of dp with -1.
        for (int i = 0; i < dp.GetLength(0); i++) {
            for (int j = 0; j < dp.GetLength(1); j++) {
                dp[i, j] = -1;
            }
        }
 
        // Function Call
        Console.WriteLine("Maximum Points We Can Make: "
                          + Sub(points, 0, 0));
    }
}


Javascript




// Javascript code for the above approach
 
// dp to store all possible state answers.
let dp = [];
 
function sub(points, last, index) {
    // Just return if u have done with all work.
    if (index == points.length)
        return 0;
 
    // if u have previously explored the state
    // give the most optimal answer.
    if (dp[index][last] != -1)
        return dp[index][last];
 
    // Store the most optimal answer for the current
    // index and last activity.
    let ans = 0;
 
    // if this is the first activity
    if (last == 0) {
        ans = Math.max(
            ans,
            Math.max(
                points[index][0] +
                sub(points, 1, index + 1),
                Math.max(
                    points[index][1] +
                    sub(points, 2, index + 1),
                    points[index][2] +
                    sub(points, 3, index + 1))));
    }
 
    // if we have selected the first
    // activity in the last try.
    else if (last == 1) {
        ans = Math.max(
            ans,
            Math.max(points[index][1] +
                sub(points, 2, index + 1),
                points[index][2] +
                sub(points, 3, index + 1)));
    }
 
    // if we have selected the second
    // activity in the last try.
    else if (last == 2) {
        ans = Math.max(
            ans,
            Math.max(points[index][0] +
                sub(points, 1, index + 1),
                points[index][2] +
                sub(points, 3, index + 1)));
    }
 
    // if we have selected the third activity
    // in the last try.
    else {
        ans = Math.max(
            ans,
            Math.max(points[index][1] +
                sub(points, 2, index + 1),
                points[index][0] +
                sub(points, 1, index + 1)));
    }
 
    // Save the maximum possible points that we
    // can get on this index with this
    // last activity.
    return dp[index][last] = ans;
}
 
// Drivers code
const n = 3;
const points = [
    [1, 2, 5],
    [3, 1, 1],
    [3, 3, 3]
];
 
// init all state of dp with -1.
dp = Array.from({
    length: points.length
}, () => Array(4).fill(-1))
 
// Function Call
console.log("Maximum Points We Can Make : " +
    sub(points, 0, 0));
 
// This code is contributed by ragul21


Output

Maximum Points We Can Make : 11









Time Complexity : O(N*3)
Auxiliary Space : O(N*4) or O(100001 * 4)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads