Open In App

Minimize the sum after choosing elements from the given three arrays

Improve
Improve
Like Article
Like
Save
Share
Report

Given three arrays A[], B[] and C[] of same size N. The task is to minimize the sum after choosing N elements from these array such that at every index i an element from any one of the array A[i], B[i] or C[i] can be chosen and no two consecutive elements can be chosen from the same array.
Examples: 

Input: A[] = {1, 100, 1}, B[] = {100, 100, 100}, C[] = {100, 100, 100} 
Output: 102 
A[0] + B[1] + A[2] = 1 + 100 + 100 = 201 
A[0] + B[1] + C[2] = 1 + 100 + 100 = 201 
A[0] + C[1] + B[2] = 1 + 100 + 100 = 201 
A[0] + C[1] + A[2] = 1 + 100 + 1 = 102 
B[0] + A[1] + B[2] = 100 + 100 + 100 = 300 
B[0] + A[1] + C[2] = 100 + 100 + 100 = 300 
B[0] + C[1] + A[2] = 100 + 100 + 1 = 201 
B[0] + C[1] + B[2] = 100 + 100 + 100 = 300 
C[0] + A[1] + B[2] = 100 + 100 + 100 = 300 
C[0] + A[1] + C[2] = 100 + 100 + 100 = 300 
C[0] + B[1] + A[2] = 100 + 100 + 1 = 201 
C[0] + B[1] + C[2] = 100 + 100 + 100 = 300
Input: A[] = {1, 1, 1}, B[] = {1, 1, 1}, C[] = {1, 1, 1} 
Output:

Approach: The problem is a simple variation of finding minimum cost. The extra constraint are that if we take an element from a particular array then we cannot take the next element from the same array. This could easily be solved using recursion but it would give time complexity as O(3^n) because for every element we have three arrays as choices.
To improve the time complexity we can easily store the pre-calculated values in a dp array.
Since there are three arrays to choose from at every index, three cases arise in this scenario: 

  • Case 1: If array A[] is selected from the ith element then we either choose the array B[] or the array C[] for the (i + 1)th element.
  • Case 2: If array B[] is selected from the ith element then we either choose the array A[] or the array C[] for the (i + 1)th element.
  • Case 3: If array C[] is selected from the ith element then we either choose the array A[] or the array B[] for the (i + 1)th element.

The above states can be solved using recursion and intermediate results can be stored in the dp array.
Below is the implementation of the above approach:

C++




// C++ implementation of the above approach
 
#include <bits/stdc++.h>
using namespace std;
#define SIZE 3
const int N = 3;
 
// Function to return the minimized sum
int minSum(int A[], int B[], int C[], int i,
        int n, int curr, int dp[SIZE][N])
{
 
    // If all the indices have been used
    if (n <= 0)
        return 0;
 
    // If this value is pre-calculated
    // then return its value from dp array
    // instead of re-computing it
    if (dp[n][curr] != -1)
        return dp[n][curr];
 
    // Here curr is the array chosen
    // for the (i - 1)th element
    // 0 for A[], 1 for B[] and 2 for C[]
 
    // If A[i - 1] was chosen previously then
    // only B[i] or C[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    if (curr == 0) {
        return dp[n][curr]
                = min(B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp),
                      C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
    }
 
    // If B[i - 1] was chosen previously then
    // only A[i] or C[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    if (curr == 1)
        return dp[n][curr]
                = min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                      C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
 
    // If C[i - 1] was chosen previously then
    // only A[i] or B[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    return dp[n][curr]
                = min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                      B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp));
}
 
// Driver code
int main()
{
    int A[] = { 1, 50, 1 };
    int B[] = { 50, 50, 50 };
    int C[] = { 50, 50, 50 };
 
    // Initialize the dp[][] array
    int dp[SIZE][N];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < N; j++)
            dp[i][j] = -1;
 
    // min(start with A[0], start with B[0], start with C[0])
    cout << min(A[0] + minSum(A, B, C, 1, SIZE - 1, 0, dp),
                min(B[0] + minSum(A, B, C, 1, SIZE - 1, 1, dp),
                    C[0] + minSum(A, B, C, 1, SIZE - 1, 2, dp)));
 
    return 0;
}


Java




// Java implementation of the above approach
import java.io.*;
 
class GFG
{
 
static int SIZE = 3;
static int N = 3;
 
// Function to return the minimized sum
static int minSum(int A[], int B[], int C[], int i,
                    int n, int curr, int [][]dp)
{
 
    // If all the indices have been used
    if (n <= 0)
        return 0;
 
    // If this value is pre-calculated
    // then return its value from dp array
    // instead of re-computing it
    if (dp[n][curr] != -1)
        return dp[n][curr];
 
    // Here curr is the array chosen
    // for the (i - 1)th element
    // 0 for A[], 1 for B[] and 2 for C[]
 
    // If A[i - 1] was chosen previously then
    // only B[i] or C[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    if (curr == 0)
    {
        return dp[n][curr]
                = Math.min(B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp),
                    C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
    }
 
    // If B[i - 1] was chosen previously then
    // only A[i] or C[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    if (curr == 1)
        return dp[n][curr]
                = Math.min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                    C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
 
    // If C[i - 1] was chosen previously then
    // only A[i] or B[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    return dp[n][curr]
                = Math.min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                    B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp));
}
 
// Driver code
public static void main (String[] args)
{
    int A[] = { 1, 50, 1 };
    int B[] = { 50, 50, 50 };
    int C[] = { 50, 50, 50 };
     
    // Initialize the dp[][] array
    int dp[][] = new int[SIZE][N];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < N; j++)
            dp[i][j] = -1;
     
    // min(start with A[0], start with B[0], start with C[0])
    System.out.println(Math.min(A[0] + minSum(A, B, C, 1, SIZE - 1, 0, dp),
                Math.min(B[0] + minSum(A, B, C, 1, SIZE - 1, 1, dp),
                    C[0] + minSum(A, B, C, 1, SIZE - 1, 2, dp))));
}
}
 
// This code is contributed by anuj_67..


Python3




# Python3 implementation of the above approach
 
import numpy as np
 
SIZE = 3;
N = 3;
 
# Function to return the minimized sum
def minSum(A, B, C, i, n, curr, dp) :
 
    # If all the indices have been used
    if (n <= 0) :
        return 0;
 
    # If this value is pre-calculated
    # then return its value from dp array
    # instead of re-computing it
    if (dp[n][curr] != -1) :
        return dp[n][curr];
 
    # Here curr is the array chosen
    # for the (i - 1)th element
    # 0 for A[], 1 for B[] and 2 for C[]
 
    # If A[i - 1] was chosen previously then
    # only B[i] or C[i] can chosen now
    # choose the one which leads
    # to the minimum sum
    if (curr == 0) :
        dp[n][curr] = min( B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp),
        C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
        return dp[n][curr]
     
 
    # If B[i - 1] was chosen previously then
    # only A[i] or C[i] can chosen now
    # choose the one which leads
    # to the minimum sum
    if (curr == 1) :
        dp[n][curr] = min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
        C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
        return dp[n][curr]
 
    # If C[i - 1] was chosen previously then
    # only A[i] or B[i] can chosen now
    # choose the one which leads
    # to the minimum sum
    dp[n][curr] = min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
    B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp));
     
    return dp[n][curr]
 
 
# Driver code
if __name__ == "__main__" :
 
    A = [ 1, 50, 1 ];
    B = [ 50, 50, 50 ];
    C = [ 50, 50, 50 ];
 
    # Initialize the dp[][] array
    dp = np.zeros((SIZE,N));
     
    for i in range(SIZE) :
        for j in range(N) :
            dp[i][j] = -1;
 
    # min(start with A[0], start with B[0], start with C[0])
    print(min(A[0] + minSum(A, B, C, 1, SIZE - 1, 0, dp),
                min(B[0] + minSum(A, B, C, 1, SIZE - 1, 1, dp),
                C[0] + minSum(A, B, C, 1, SIZE - 1, 2, dp))));
 
# This code is contributed by AnkitRai01


C#




// C# implementation of the above approach
using System;
 
class GFG
{
 
static int SIZE = 3;
static int N = 3;
 
// Function to return the minimized sum
static int minSum(int []A, int []B, int []C, int i,
                    int n, int curr, int [,]dp)
{
 
    // If all the indices have been used
    if (n <= 0)
        return 0;
 
    // If this value is pre-calculated
    // then return its value from dp array
    // instead of re-computing it
    if (dp[n,curr] != -1)
        return dp[n,curr];
 
    // Here curr is the array chosen
    // for the (i - 1)th element
    // 0 for A[], 1 for B[] and 2 for C[]
 
    // If A[i - 1] was chosen previously then
    // only B[i] or C[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    if (curr == 0)
    {
        return dp[n,curr]
                = Math.Min(B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp),
                    C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
    }
 
    // If B[i - 1] was chosen previously then
    // only A[i] or C[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    if (curr == 1)
        return dp[n,curr]
                = Math.Min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                    C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
 
    // If C[i - 1] was chosen previously then
    // only A[i] or B[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    return dp[n,curr]
                = Math.Min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                    B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp));
}
 
// Driver code
public static void Main ()
{
    int []A = { 1, 50, 1 };
    int []B = { 50, 50, 50 };
    int []C = { 50, 50, 50 };
     
    // Initialize the dp[][] array
    int [,]dp = new int[SIZE,N];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < N; j++)
            dp[i,j] = -1;
     
    // min(start with A[0], start with B[0], start with C[0])
    Console.WriteLine(Math.Min(A[0] + minSum(A, B, C, 1, SIZE - 1, 0, dp),
                Math.Min(B[0] + minSum(A, B, C, 1, SIZE - 1, 1, dp),
                    C[0] + minSum(A, B, C, 1, SIZE - 1, 2, dp))));
}
}
 
// This code is contributed by anuj_67..


Javascript




<script>
    // Javascript implementation of the above approach
     
    let SIZE = 3;
    let N = 3;
 
    // Function to return the minimized sum
    function minSum(A, B, C, i, n, curr, dp)
    {
 
        // If all the indices have been used
        if (n <= 0)
            return 0;
 
        // If this value is pre-calculated
        // then return its value from dp array
        // instead of re-computing it
        if (dp[n][curr] != -1)
            return dp[n][curr];
 
        // Here curr is the array chosen
        // for the (i - 1)th element
        // 0 for A[], 1 for B[] and 2 for C[]
 
        // If A[i - 1] was chosen previously then
        // only B[i] or C[i] can chosen now
        // choose the one which leads
        // to the minimum sum
        if (curr == 0)
        {
            return dp[n][curr]
                    = Math.min(B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp),
                        C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
        }
 
        // If B[i - 1] was chosen previously then
        // only A[i] or C[i] can chosen now
        // choose the one which leads
        // to the minimum sum
        if (curr == 1)
            return dp[n][curr]
                    = Math.min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                        C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
 
        // If C[i - 1] was chosen previously then
        // only A[i] or B[i] can chosen now
        // choose the one which leads
        // to the minimum sum
        return dp[n][curr]
                    = Math.min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                        B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp));
    }
     
    let A = [ 1, 50, 1 ];
    let B = [ 50, 50, 50 ];
    let C = [ 50, 50, 50 ];
       
    // Initialize the dp[][] array
    let dp = new Array(SIZE);
    for (let i = 0; i < SIZE; i++)
    {
        dp[i] = new Array(N);
        for (let j = 0; j < N; j++)
        {
            dp[i][j] = -1;
        }
    }
       
    // min(start with A[0], start with B[0], start with C[0])
    document.write(Math.min(A[0] + minSum(A, B, C, 1, SIZE - 1, 0, dp),
                Math.min(B[0] + minSum(A, B, C, 1, SIZE - 1, 1, dp),
                    C[0] + minSum(A, B, C, 1, SIZE - 1, 2, dp))));
 
</script>


Output

52



Time Complexity: O(SIZE*N), where dp operations taking SIZE*N time
Auxiliary Space: O(SIZE*N), where dp array is made of two states SIZE*N

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 :

  • Create a DP to store the solution of the subproblems.
  • Initialize the DP  with base cases
  • Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP.
  • Return the final solution minimum of min(dp[0][0], min(dp[0][1], dp[0][2])).

Implementation :

C++




#include <iostream>
using namespace std;
 
const int SIZE = 3;
 
// Function to return the minimized sum
int minSum(int A[], int B[], int C[]) {
    int dp[SIZE][3];
 
    // Base case
    dp[SIZE-1][0] = A[SIZE-1];
    dp[SIZE-1][1] = B[SIZE-1];
    dp[SIZE-1][2] = C[SIZE-1];
 
    // Tabulate the solution from bottom up
    for(int i = SIZE-2; i >= 0; i--) {
       
          // iterate over subproblems to get the current
          // value from previous computaions
        dp[i][0] = A[i] + min(dp[i+1][1], dp[i+1][2]);
        dp[i][1] = B[i] + min(dp[i+1][0], dp[i+1][2]);
        dp[i][2] = C[i] + min(dp[i+1][0], dp[i+1][1]);
    }
 
    // Return the minimized sum
    return min(dp[0][0], min(dp[0][1], dp[0][2]));
}
 
// Driver code
int main() {
    int A[] = { 1, 50, 1 };
    int B[] = { 50, 50, 50 };
    int C[] = { 50, 50, 50 };
     
      // function call
    cout << minSum(A, B, C) << endl;
    return 0;
}


Java




// Java program to return the minimized sum
public class Main {
    public static void main(String[] args) {
        int SIZE = 3;
        int[] A = { 1, 50, 1 };
        int[] B = { 50, 50, 50 };
        int[] C = { 50, 50, 50 };
 
        int[][] dp = new int[SIZE][3];
 
        // Base case
        dp[SIZE - 1][0] = A[SIZE - 1];
        dp[SIZE - 1][1] = B[SIZE - 1];
        dp[SIZE - 1][2] = C[SIZE - 1];
 
        // Tabulate the solution from bottom up
        for (int i = SIZE - 2; i >= 0; i--) {
 
            // Iterate over subproblems to get the current
            // value from previous computations
            dp[i][0] = A[i] + Math.min(dp[i + 1][1], dp[i + 1][2]);
            dp[i][1] = B[i] + Math.min(dp[i + 1][0], dp[i + 1][2]);
            dp[i][2] = C[i] + Math.min(dp[i + 1][0], dp[i + 1][1]);
        }
 
        // Return the minimized sum
        int result = Math.min(dp[0][0], Math.min(dp[0][1], dp[0][2]));
        System.out.println(result);
    }
}


Python3




import sys
 
SIZE = 3
 
# Function to return the minimized sum
 
 
def minSum(A, B, C):
    dp = [[0 for j in range(3)] for i in range(SIZE)]
 
    # Base case
    dp[SIZE-1][0] = A[SIZE-1]
    dp[SIZE-1][1] = B[SIZE-1]
    dp[SIZE-1][2] = C[SIZE-1]
 
    # Tabulate the solution from bottom up
    for i in range(SIZE-2, -1, -1):
        # iterate over subproblems to get the current
        # value from previous computaions
        dp[i][0] = A[i] + min(dp[i+1][1], dp[i+1][2])
        dp[i][1] = B[i] + min(dp[i+1][0], dp[i+1][2])
        dp[i][2] = C[i] + min(dp[i+1][0], dp[i+1][1])
 
    # Return the minimized sum
    return min(dp[0][0], min(dp[0][1], dp[0][2]))
 
 
# Driver code
if __name__ == '__main__':
    A = [1, 50, 1]
    B = [50, 50, 50]
    C = [50, 50, 50]
 
    # function call
    print(minSum(A, B, C))


C#




using System;
 
class Program
{
    const int SIZE = 3;
 
    // Function to return the minimized sum
    static int MinSum(int[] A, int[] B, int[] C)
    {
        int[,] dp = new int[SIZE, 3];
 
        // Base case
        dp[SIZE - 1, 0] = A[SIZE - 1];
        dp[SIZE - 1, 1] = B[SIZE - 1];
        dp[SIZE - 1, 2] = C[SIZE - 1];
 
        // Tabulate the solution from bottom up
        for (int i = SIZE - 2; i >= 0; i--)
        {
            // Iterate over subproblems to get the current
            // value from previous computations
            dp[i, 0] = A[i] + Math.Min(dp[i + 1, 1], dp[i + 1, 2]);
            dp[i, 1] = B[i] + Math.Min(dp[i + 1, 0], dp[i + 1, 2]);
            dp[i, 2] = C[i] + Math.Min(dp[i + 1, 0], dp[i + 1, 1]);
        }
 
        // Return the minimized sum
        return Math.Min(dp[0, 0], Math.Min(dp[0, 1], dp[0, 2]));
    }
 
    // Driver Code
    static void Main()
    {
        int[] A = { 1, 50, 1 };
        int[] B = { 50, 50, 50 };
        int[] C = { 50, 50, 50 };
 
        // Function call
        Console.WriteLine(MinSum(A, B, C));
    }
}


Javascript




const SIZE = 3;
 
// Function to return the minimized sum
function minSum(A, B, C) {
    const dp = new Array(SIZE).fill().map(() => new Array(3));
 
    // Base case
    dp[SIZE - 1][0] = A[SIZE - 1];
    dp[SIZE - 1][1] = B[SIZE - 1];
    dp[SIZE - 1][2] = C[SIZE - 1];
 
    // Tabulate the solution from bottom up
    for (let i = SIZE - 2; i >= 0; i--) {
        // Iterate over subproblems to get the current
        // value from previous computations
        dp[i][0] = A[i] + Math.min(dp[i + 1][1], dp[i + 1][2]);
        dp[i][1] = B[i] + Math.min(dp[i + 1][0], dp[i + 1][2]);
        dp[i][2] = C[i] + Math.min(dp[i + 1][0], dp[i + 1][1]);
    }
 
    // Return the minimized sum
    return Math.min(dp[0][0], Math.min(dp[0][1], dp[0][2]));
}
 
// Driver code
const A = [1, 50, 1];
const B = [50, 50, 50];
const C = [50, 50, 50];
 
// Function call
console.log(minSum(A, B, C));


Output

52



Time Complexity: O(n), where n is the size of the arrays A, B, and C.
Auxiliary Space: O(n), as the dp array has n rows and 3 columns



Last Updated : 09 Oct, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads