Minimize the sum after choosing elements from the given three arrays
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