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: 3Â
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> |
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)); |
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
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!