Open In App

# 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 = 25

Input: 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``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

 ``

Output:

`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