Open In App

Maximize score by matching element with prediction and K switch are allowed

Last Updated : 28 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

 Given an array arr[] of size N, with values either 1, 2, or 3. Traverse the array from left to right and before traversal predict one number from 1, 2, or 3, if arr[i] is matched with the prediction score will be increased by 1. The prediction can be switched at most K times. Find the maximum score possible.

Examples:

 Input: A[] = {1, 1, 2, 1, 3}, K = 1
Output: 4
Explanation:
Following is the optimal way to perform the above operations:
Initially choose P = 1 for the i = 0 as number matches with A[0] = 1, received 1 point.
For i = 1, A[1] = 1 and we did not change chosen number P = 1 , as A[1] and P are equal we received another 1 point. 
For i = 2, A[2] = 2 and we did not change chosen number P = 1 so, we do not receive point since P != A[2].
For i = 3, A[3] = 1 and we did  not change chosen number P = 1 so, we receives another one point since P = A[3].
For i = 4, A[4] = 3 and we switch P to 3 since we can make a switch at most K = 1 times. P = 3 and A[4] is also 3 so we receive another point.
With this strategy, we receive a total of 4 points.

Input: A[] = {3, 3, 1, 3, 3, 2, 2, 2 }, K = 0
Output: 4
Explanation: It is optimal to choose 3 for all indices since we cannot make changes once we select a particular number because K = 0.

Naive approach: The basic way to solve the problem is as follows:

The basic way to solve this problem is to explore all possible combinations by using a recursive approach.

Time Complexity: O(2N)
Auxiliary Space: O(1)

Efficient Approach:  The above approach can be optimized based on the following idea:

Dynamic programming can be used to solve this problem.

dp[i][j][k] represents the maximum score till ith element with j chosen in the last match along with k switches left. 
Recurrence relation is one of the following depending upon the value of K  and we are switching to which number:

  • dp[i][j]k] = max(dp[i + 1][1][k] + (A[i] == 1), dp[i + 1][2][k – 1] + (A[i] == 2), dp[i + 1][3][k – 1] + (A[i] == 3))          
  • dp[i][j]k] = max(dp[i + 1][1][k – 1] + (A[i] == 1), dp[i + 1][2][k] + (A[i] == 2), dp[i + 1][3][k – 1] + (A[i] == 3))
  • dp[i][j]k] = max(dp[i + 1][1][k – 1] + (A[i] == 1), dp[i + 1][2][k – 1] + (A[i] == 2), dp[i + 1][3][k] + (A[i] == 3))

It can be observed that the recursive function is called exponential times. That means that some states are called repeatedly. So the idea is to store the value of each state.

Follow the steps below to solve the problem:

  • Create a 3d array of dp[N][5][21] initially filled with -1.
  • Create a recursive function that takes three parameters i representing ith element,, j representing the last element chosen, and k representing the number of switches left.
  • Check the base case, if all matches over return 0.
  • If the answer for a particular state is computed then save it in dp[i][j][k].
  • Otherwise, call the recursive function three times for choosing all three numbers.
  • If the answer for a particular state is already computed then just return dp[i][j][k].

Below is the implementation of the above approach.

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// dp table initialization
int dp[100001][5][21];
 
// Recursive function to calculate maximum
// score from traversing left to right.
int recur(int i, int j, int k, int A[], int N)
{
    // Base case
    if (i == N) {
        return 0;
    }
 
    // If answer for current state is already
    // calculated then just return dp[i][j]
    if (dp[i][j + 1][k] != -1)
        return dp[i][j + 1][k];
 
    int ans = INT_MIN;
 
    // Calling recursive function for choosing 1
    if ((k != 0) or (k == 0 and j == 1))
        ans = max(
            ans, recur(i + 1, 1, (j == 1) ? k : k - 1, A, N)
                     + (A[i] == 1));
 
    // Calling recursive function for choosing 2
    if ((k != 0) or (k == 0 and j == 2))
        ans = max(
            ans, recur(i + 1, 2, (j == 2) ? k : k - 1, A, N)
                     + (A[i] == 2));
 
    // Calling recursive function for choosing 3
    if ((k != 0) or (k == 0 and j == 3))
        ans = max(
            ans, recur(i + 1, 3, (j == 3) ? k : k - 1, A, N)
                     + (A[i] == 3));
 
    // Save and return dp value
    return dp[i][j + 1][k] = ans;
}
 
// Function to calculate maximum score
// by traversing left to right
int minCost(int A[], int N, int K)
{
    // Filling dp table with -1
    memset(dp, -1, sizeof(dp));
 
    // Calling the utility function
    return recur(0, -1, K + 1, A, N);
}
 
// Driver Code
int main()
{
    // Test Case 1
    int A[] = { 1, 1, 2, 1, 3 }, K = 1;
    int N = sizeof(A) / sizeof(A[0]);
 
    // Function Call
    cout << minCost(A, N, K) << endl;
 
    // Test Case 2
    int A1[] = { 3, 3, 1, 3, 3, 2, 2, 2 }, K1 = 0;
    int N1 = sizeof(A1) / sizeof(A1[0]);
 
    // Function Call
    cout << minCost(A1, N1, K1) << endl;
 
    return 0;
}


Java




// Java code to implement the approach
import java.io.*;
import java.util.*;
 
class GFG {
 
  // dp table initialization
  static int[][][] dp = new int[100001][5][21];
 
  // Recursive function to calculate maximum
  // score from traversing left to right.
  static int recur(int i, int j, int k, int[] A, int N)
  {
    // Base case
    if (i == N) {
      return 0;
    }
 
    // If answer for current state is already
    // calculated then just return dp[i][j]
    if (dp[i][j + 1][k] != -1)
      return dp[i][j + 1][k];
 
    int ans = Integer.MIN_VALUE;
 
    // Calling recursive function for choosing 1
    if ((k != 0) || (k == 0 && j == 1))
      ans = Math.max(
      ans,
      recur(i + 1, 1, (j == 1) ? k : k - 1, A, N)
      + (A[i] == 1 ? 1 : 0));
 
    // Calling recursive function for choosing 2
    if ((k != 0) || (k == 0 && j == 2))
      ans = Math.max(
      ans,
      recur(i + 1, 2, (j == 2) ? k : k - 1, A, N)
      + (A[i] == 2 ? 1 : 0));
 
    // Calling recursive function for choosing 3
    if ((k != 0) || (k == 0 && j == 3))
      ans = Math.max(
      ans,
      recur(i + 1, 3, (j == 3) ? k : k - 1, A, N)
      + (A[i] == 3 ? 1 : 0));
 
    // Save and return dp value
    return dp[i][j + 1][k] = ans;
  }
 
  // Function to calculate maximum score
  // by traversing left to right
  static int minCost(int[] A, int N, int K)
  {
    // Filling dp table with -1
    for (int[][] dp1 : dp) {
      for (int[] dp11 : dp1) {
        Arrays.fill(dp11, -1);
      }
    }
 
    // Calling the utility function
    return recur(0, -1, K + 1, A, N);
  }
 
  public static void main(String[] args)
  {
    // Test Case 1
    int[] A = { 1, 1, 2, 1, 3 };
    int K = 1;
    int N = A.length;
 
    // Function Call
    System.out.println(minCost(A, N, K));
 
    // Test Case 2
    int[] A1 = { 3, 3, 1, 3, 3, 2, 2, 2 };
    int K1 = 0;
    int N1 = A1.length;
 
    // Function Call
    System.out.println(minCost(A1, N1, K1));
  }
}
 
// This code is contributed by lokesh.


Python3




import sys
 
# dp table initialization
dp = [[[-1 for _ in range(21)] for _ in range(5)] for _ in range(100001)]
 
# Recursive function to calculate maximum score from traversing left to right.
def recur(i, j, k, A, N):
    # Base case
    if i == N:
        return 0
    # If answer for current state is already calculated then just return dp[i][j]
    if dp[i][j + 1][k] != -1:
        return dp[i][j + 1][k]
 
    ans = -sys.maxsize
 
    # Calling recursive function for choosing 1
    if k != 0 or (k == 0 and j == 1):
        ans = max(
            ans, recur(i + 1, 1, k - 1 if j != 1 else k, A, N) + (A[i] == 1)
        )
 
    # Calling recursive function for choosing 2
    if k != 0 or (k == 0 and j == 2):
        ans = max(
            ans, recur(i + 1, 2, k - 1 if j != 2 else k, A, N) + (A[i] == 2)
        )
 
    # Calling recursive function for choosing 3
    if k != 0 or (k == 0 and j == 3):
        ans = max(
            ans, recur(i + 1, 3, k - 1 if j != 3 else k, A, N) + (A[i] == 3)
        )
 
    # Save and return dp value
    dp[i][j + 1][k] = ans
    return dp[i][j + 1][k]
 
# Function to calculate maximum score by traversing left to right
def minCost(A, N, K):
    # Filling dp table with -1
    global dp
    dp = [[[-1 for _ in range(21)] for _ in range(5)] for _ in range(N + 1)]
    # Calling the utility function
    return recur(0, -1, K + 1, A, N)
 
# Driver Code
if __name__ == '__main__':
    # Test Case 1
    A = [1, 1, 2, 1, 3]
    K = 1
    N = len(A)
    # Function Call
    print(minCost(A, N, K))
 
    # Test Case 2
    A1 = [3, 3, 1, 3, 3, 2, 2, 2]
    K1 = 0
    N1 = len(A1)
 
    # Function Call
    print(minCost(A1, N1, K1))


C#




// C# code to implement the approach
using System;
 
public class GFG {
 
  // dp table initialization
  static int[, , ] dp = new int[100001, 5, 21];
 
  // Recursive function to calculate maximum
  // score from traversing left to right.
  static int recur(int i, int j, int k, int[] A, int N)
  {
    // Base case
    if (i == N) {
      return 0;
    }
 
    // If answer for current state is already
    // calculated then just return dp[i][j]
    if (dp[i, j + 1, k] != -1) {
      return dp[i, j + 1, k];
    }
 
    int ans = int.MinValue;
 
    // Calling recursive function for choosing 1
    if ((k != 0) || (k == 0 && j == 1)) {
      ans = Math.Max(
        ans,
        recur(i + 1, 1, (j == 1) ? k : k - 1, A, N)
        + (A[i] == 1 ? 1 : 0));
    }
 
    // Calling recursive function for choosing 2
    if ((k != 0) || (k == 0 && j == 2)) {
      ans = Math.Max(
        ans,
        recur(i + 1, 2, (j == 2) ? k : k - 1, A, N)
        + (A[i] == 2 ? 1 : 0));
    }
 
    // Calling recursive function for choosing 3
    if ((k != 0) || (k == 0 && j == 3)) {
      ans = Math.Max(
        ans,
        recur(i + 1, 3, (j == 3) ? k : k - 1, A, N)
        + (A[i] == 3 ? 1 : 0));
    }
 
    // Save and return dp value
    return dp[i, j + 1, k] = ans;
  }
 
  // Function to calculate maximum score
  // by traversing left to right
  static int minCost(int[] A, int N, int K)
  {
    // Filling dp table with -1
    for (int i = 0; i < dp.GetLength(0); i++) {
      for (int j = 0; j < dp.GetLength(1); j++) {
        for (int l = 0; l < dp.GetLength(2); l++) {
          dp[i, j, l] = -1;
        }
      }
    }
 
    // Calling the utility function
    return recur(0, -1, K + 1, A, N);
  }
 
  static public void Main()
  {
 
    // Code
    // Test Case 1
    int[] A = { 1, 1, 2, 1, 3 };
    int K = 1;
    int N = A.Length;
 
    // Function Call
    Console.WriteLine(minCost(A, N, K));
 
    // Test Case 2
    int[] A1 = { 3, 3, 1, 3, 3, 2, 2, 2 };
    int K1 = 0;
    int N1 = A1.Length;
 
    // Function Call
    Console.WriteLine(minCost(A1, N1, K1));
  }
}
 
// This code is contributed by lokeshmvs21.


Javascript




// Javascript code to implement the approach
 
function minCost(A, N, K) {
// dp table initialization
    let dp = [];
    for (let i = 0; i <= N; i++) {
        dp[i] = [];
        for (let j = 0; j <= 4; j++) {
            dp[i][j] = [];
            for (let k = 0; k <= 21; k++) {
                dp[i][j][k] = -1;
            }
        }
    }
// Recursive function to calculate maximum score from traversing left to right.
    function recur(i, j, k) {
     // Base case
        if (i === N) {
            return 0;
        }
 
    // If answer for current state is already calculated then just return dp[i][j]
        if (dp[i][j + 1][k] !== -1) {
            return dp[i][j + 1][k];
        }
 
        let ans = Number.MIN_SAFE_INTEGER;
// Calling recursive function for choosing 1
        if ((k !== 0) || (k === 0 && j === 1)) {
            ans = Math.max(
                ans, recur(i + 1, 1, (j === 1) ? k : k - 1) + (A[i] === 1)
            );
        }
// Calling recursive function for choosing 2
        if ((k !== 0) || (k === 0 && j === 2)) {
            ans = Math.max(
                ans, recur(i + 1, 2, (j === 2) ? k : k - 1) + (A[i] === 2)
            );
        }
// Calling recursive function for choosing 3
        if ((k !== 0) || (k === 0 && j === 3)) {
            ans = Math.max(
                ans, recur(i + 1, 3, (j === 3) ? k : k - 1) + (A[i] === 3)
            );
        }
 
        return dp[i][j + 1][k] = ans;
    }
 
    return recur(0, -1, K + 1);
}
// Test Case 1
let A = [1, 1, 2, 1, 3];
let K = 1;
let N = A.length;
// Function Call
console.log(minCost(A, N, K));
// Test Case 2
let A1 = [3, 3, 1, 3, 3, 2, 2, 2];
let K1 = 0;
let N1 = A1.length;
// Function Call
console.log(minCost(A1, N1, K1));
 
// code by ksam24000


Output

4
4

Time Complexity: O(N)
Auxiliary Space: O(N)

Related Articles :



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads