Minimize cost to reduce array to a single element by replacing K consecutive elements by their sum
Given an array arr[] of size N and an integer K, the task is to find the minimum cost required to reduce given array to a single element, where cost of replacing K consecutive array elements by their sum is equal to the sum of the K consecutive elements. If it is not possible to reduce given array to a single element, then print -1.
Examples:
Input: arr[] = {3, 5, 1, 2, 6}, K = 3
Output: 25
Explanation:
Replacing {arr[1], arr[2], arr[3]} modifies arr[] = {3, 8, 6}. Cost = 8
Replacing {arr[0], arr[1], arr[2]} modifies arr[] = {17}. Cost = 17.
Therefore, the total cost to merge all the array elements into one = 8 + 17 = 25Input: arr[] = {3, 2, 4, 1}, K = 3
Output: -1
Merging any K (=3) consecutive array elements left 2 elements in the array.
Therefore, the required output is -1.
Approach: The problem can be solved using Dynamic programming. Following is the recurrence relation:
Since the size of the array reduces by (K – 1) after every replacement operation,
dp[i][j] = min(dp[i][x], dp[x+1][j]), X = i + integer * (K – 1)
where, dp[i][j] stores the minimum cost to merge maximum number of array elements in the interval [i, j] with the left most element arr[i] always involved in merge if possible
Follow the steps below to solve the problem:
- If (N – 1) % (K – 1) != 0 then print -1.
- Initialize an array, say prefixSum[] to store the prefix sum of the given array.
- Initialize a 2D array, say dp[][], where dp[i][j] stores the minimum cost to merge the max number of array elements in the interval [i, j].
- Fill the DP table using the above-mentioned relationship between the DP states.
- Finally, print the value of dp[0][N – 1].
Below is the implementation of the above approach:
C++
// C++ program to implement // the above approach #include<bits/stdc++.h> using namespace std; // Function to find the minimum cost // to reduce given array to a single // element by replacing consecutive // K array elements int minimumCostToMergeK( int arr[], int K, int N) { // If (N - 1) is not // multiple of (K - 1) if ((N - 1) % (K - 1) != 0) { return -1; } // Store prefix sum of the array int prefixSum[N + 1] = {0}; // Iterate over the range [1, N] for ( int i = 1; i < (N + 1); i++) { // Update prefixSum[i] prefixSum[i] = (prefixSum[i - 1] + arr[i - 1]); } // dp[i][j]: Store minimum cost to // merge array elements interval [i, j] int dp[N][N]; memset (dp, 0, sizeof (dp)); // L: Stores length of interval [i, j] for ( int L = K; L < (N + 1); L++) { // Iterate over each interval // [i, j] of length L in in [0, N] for ( int i = 0; i < (N - L + 1); i++) { // Stores index of last element // of the interval [i, j] int j = i + L - 1; // If L is greater than K if (L > K) { int temp = INT_MAX; for ( int x = i; x < j; x += K - 1) { temp = min(temp, dp[i][x] + dp[x + 1][j]); } // Update dp[i][j] dp[i][j] = temp; } // If (L - 1) is multiple of (K - 1) if ((L - 1) % (K - 1) == 0) { // Update dp[i][j] dp[i][j] += (prefixSum[j + 1] - prefixSum[i]); } } } // Return dp[0][N - 1] return dp[0][N - 1]; } // Driver Code int main() { int arr[] = { 3, 5, 1, 2, 6 }; int K = 3; // Stores length of arr int N = sizeof (arr) / sizeof (arr[0]); cout << minimumCostToMergeK(arr, K, N); } // This code is contributed by rag2127 |
Java
// Java program to implement // the above approach import java.util.*; class GFG { // Function to find the minimum cost // to reduce given array to a single // element by replacing consecutive // K array elements static int minimumCostToMergeK( int arr[], int K, int N) { // If (N - 1) is not // multiple of (K - 1) if ((N - 1 ) % (K - 1 ) != 0 ) { return - 1 ; } // Store prefix sum of the array int []prefixSum = new int [N + 1 ]; // Iterate over the range [1, N] for ( int i = 1 ; i < (N + 1 ); i++) { // Update prefixSum[i] prefixSum[i] = (prefixSum[i - 1 ] + arr[i - 1 ]); } // dp[i][j]: Store minimum cost to // merge array elements interval [i, j] int [][]dp = new int [N][N]; // L: Stores length of interval [i, j] for ( int L = K; L < (N + 1 ); L++) { // Iterate over each interval // [i, j] of length L in in [0, N] for ( int i = 0 ; i < (N - L + 1 ); i++) { // Stores index of last element // of the interval [i, j] int j = i + L - 1 ; // If L is greater than K if (L > K) { int temp = Integer.MAX_VALUE; for ( int x = i; x < j; x += K - 1 ) { temp = Math.min(temp, dp[i][x] + dp[x + 1 ][j]); } // Update dp[i][j] dp[i][j] = temp; } // If (L - 1) is multiple of (K - 1) if ((L - 1 ) % (K - 1 ) == 0 ) { // Update dp[i][j] dp[i][j] += (prefixSum[j + 1 ] - prefixSum[i]); } } } // Return dp[0][N - 1] return dp[ 0 ][N - 1 ]; } // Driver Code public static void main(String[] args) { int arr[] = { 3 , 5 , 1 , 2 , 6 }; int K = 3 ; // Stores length of arr int N = arr.length; System.out.print(minimumCostToMergeK(arr, K, N)); } } // This code is contributed by shikhasingrajput |
Python3
# Python3 program to implement # the above approach # Function to find the minimum cost # to reduce given array to a single # element by replacing consecutive # K array elements def minimumCostToMergeK(arr, K): # Stores length of arr N = len (arr) # If (N - 1) is not # multiple of (K - 1) if (N - 1 ) % (K - 1 ) ! = 0 : return - 1 # Store prefix sum of the array prefixSum = [ 0 ] * (N + 1 ) # Iterate over the range [1, N] for i in range ( 1 , N + 1 ): # Update prefixSum[i] prefixSum[i] = (prefixSum[i - 1 ] + arr[i - 1 ]) # dp[i][j]: Store minimum cost to # merge array elements interval [i, j] dp = [[ 0 ] * N for _ in range (N)] # L: Stores length of interval [i, j] for L in range (K, N + 1 ): # Iterate over each interval # [i, j] of length L in in [0, N] for i in range (N - L + 1 ): # Stores index of last element # of the interval [i, j] j = i + L - 1 # If L is greater than K if L > K: # Update dp[i][j] dp[i][j] = ( min ([dp[i][x] + dp[x + 1 ][j] for x in range (i, j, K - 1 )])) # If (L - 1) is multiple of (K - 1) if (L - 1 ) % (K - 1 ) = = 0 : # Update dp[i][j] dp[i][j] + = (prefixSum[j + 1 ] - prefixSum[i]) # Return dp[0][N - 1] return dp[ 0 ][N - 1 ] if __name__ = = "__main__" : arr = [ 3 , 5 , 1 , 2 , 6 ] K = 3 print (minimumCostToMergeK(arr, K)) |
C#
// C# program to implement // the above approach using System; class GFG { // Function to find the minimum cost // to reduce given array to a single // element by replacing consecutive // K array elements static int minimumCostToMergeK( int []arr, int K, int N) { // If (N - 1) is not // multiple of (K - 1) if ((N - 1) % (K - 1) != 0) { return -1; } // Store prefix sum of the array int []prefixSum = new int [N + 1]; // Iterate over the range [1, N] for ( int i = 1; i < (N + 1); i++) { // Update prefixSum[i] prefixSum[i] = (prefixSum[i - 1] + arr[i - 1]); } // dp[i,j]: Store minimum cost to // merge array elements interval [i, j] int [,]dp = new int [N,N]; // L: Stores length of interval [i, j] for ( int L = K; L < (N + 1); L++) { // Iterate over each interval // [i, j] of length L in in [0, N] for ( int i = 0; i < (N - L + 1); i++) { // Stores index of last element // of the interval [i, j] int j = i + L - 1; // If L is greater than K if (L > K) { int temp = int .MaxValue; for ( int x = i; x < j; x += K - 1) { temp = Math.Min(temp, dp[i, x] + dp[x + 1, j]); } // Update dp[i,j] dp[i, j] = temp; } // If (L - 1) is multiple of (K - 1) if ((L - 1) % (K - 1) == 0) { // Update dp[i,j] dp[i, j] += (prefixSum[j + 1] - prefixSum[i]); } } } // Return dp[0,N - 1] return dp[0, N - 1]; } // Driver Code public static void Main(String[] args) { int []arr = { 3, 5, 1, 2, 6 }; int K = 3; // Stores length of arr int N = arr.Length; Console.Write(minimumCostToMergeK(arr, K, N)); } } // This code is contributed by 29AjayKumar |
Javascript
<script> // javascript program to implement // the above approach // Function to find the minimum cost // to reduce given array to a single // element by replacing consecutive // K array elements function minimumCostToMergeK(arr , K , N) { // If (N - 1) is not // multiple of (K - 1) if ((N - 1) % (K - 1) != 0) { return -1; } // Store prefix sum of the array var prefixSum = Array(N + 1).fill(0); // Iterate over the range [1, N] for (i = 1; i < (N + 1); i++) { // Update prefixSum[i] prefixSum[i] = (prefixSum[i - 1] + arr[i - 1]); } // dp[i][j]: Store minimum cost to // merge array elements interval [i, j] var dp = Array(N); for ( i = 0; i<N;i++) dp[i] = Array(N).fill(0); // L: Stores length of interval [i, j] for (L = K; L < (N + 1); L++) { // Iterate over each interval // [i, j] of length L in in [0, N] for (i = 0; i < (N - L + 1); i++) { // Stores index of last element // of the interval [i, j] var j = i + L - 1; // If L is greater than K if (L > K) { var temp = Number.MAX_VALUE; for (x = i; x < j; x += K - 1) { temp = Math.min(temp, dp[i][x] + dp[x + 1][j]); } // Update dp[i][j] dp[i][j] = temp; } // If (L - 1) is multiple of (K - 1) if ((L - 1) % (K - 1) == 0) { // Update dp[i][j] dp[i][j] += (prefixSum[j + 1] - prefixSum[i]); } } } // Return dp[0][N - 1] return dp[0][N - 1]; } // Driver Code var arr = [ 3, 5, 1, 2, 6 ]; var K = 3; // Stores length of arr var N = arr.length; document.write(minimumCostToMergeK(arr, K, N)); // This code is contributed by todaysgaurav </script> |
25
Time Complexity: O(N2 * K) // since we are using two nested loops hence the complexity is quadratic
Auxiliary Space: O(N2) // since a dp array of size n*n is used hence the space taken by the algorithm is quadratic
Please Login to comment...