We have N (where N > 2) stones of various heights laid out in a row. The task is to make a pyramid from a given array of stones. In a pyramid, the height of the stones starts from 1, increase by 1, until it reaches some value x, then decreases by 1 until it reaches 1 again i.e. the stones should be 1, 2, 3, 4…x – 1, x, x – 1, x – 2 … 1. All other stones not part of the pyramid should have a height 0. We cannot move any of the stones from their current position, however, by paying a fee of 1, we can reduce the heights of the stones. We wish to minimize the cost of building a pyramid. Output the minimum cost to build this pyramid.
Examples:
Input : 1 2 3 4 2 1 Output : 4 The best pyramid that can be formed in this case is: 1 2 3 2 1 0 The cost is thus: (4 - 2) + (2 - 1) + (1 - 0) = 4 Input : 1 5 2 Output : 4 We make a pyramid 1 2 1 Input : 1 2 1 Output : 0 We already have a pyramid, we do not need to do any further construction.
By using simple logic, we can prove that the pyramid with the least cost of construction would be that of the maximum height. Also, two temples of same heights would cost the same to construct.
This can be shown as follows:
Assume the cost of demolishing all the stones to height 0 is x.
Assume the cost of demolishing a temple of height h to height 0 is y.
Then, if it is possible to construct a temple of height h from given stones, its cost would be x – y.
By using this, we can simplify our approach to two main steps:
1. Identify the pyramid of maximum height that can be formed.
2. Calculate the cost of constructing such a pyramid.
Step 2 can be completed in O(N) time complexity assuming we know where our pyramid is placed.
Thus, our focus should be on decreasing the time complexity of step 1.
Naive Approach:
For each position in the array, we can assume the pyramid starts at that point. We then find the cost of constructing a temple of maximum height from 1 onwards, until a higher height is not possible, that is, assume a pyramid of height 1 is the maximum, then assume 2 is maximum and so on. Out of each of these costs, we then choose the minimum.
This approach uses a time complexity of O(N^3).
Improved Approach:
For each position, assume it is the center of a temple. Move to the left and right of this point and attempt to find the maximum height of the temple.
This can be done by setting the maximum of height of a temple at position i to be H(i) where H(i) is the height of the stone at that point. We then move to the left. If the height of the stone at this point is less than H(i) – 1, we set the maximum height to now be H(i – 1) + 1. In this way we identify the maximum height for each position.
This approach uses a time complexity of O(N^2).
Dynamic Programming Approach:
By modifying the above algorithm slightly, we can attempt to get an O(N) approach. Start at the left, and moving right, find the maximum possible height pyramid that can be created at that position. Assume that the part of the array to the right of that position is a mirror image of the left. If H(i) is the height of stone at position i, then maxHeight(i) = Minimum(H(i), i, maxHeight(i – 1))
This can be explained as follows:
The maximum possible height cannot exceed H(i) as we can only decrease the height of stone, not increase.
The maximum possible height cannot exceed i, as the pyramid has to start from a height 1.
The maximum possible height cannot exceed the maximum possible height of the stone before it – 1, as the stones have to increase by 1 for each step.
We calculate a similar value moving from right to left. We then take the minimum of these values for each position. Then by identifying the maximum, we can calculate the minimum cost of constructing a pyramid.
C++
// Program to find minimum cost for pyramid // from given array #include <iostream> using namespace std; #define ull unsigned long long // Returns minimum cost to form a pyramid ull minPyramidCost(ull arr[], ull N) { // Store the maximum possible pyramid height ull *left = new ull[N]; ull *right = new ull[N]; // Maximum height at start is 1 left[0] = min(arr[0], (ull)1); // For each position calculate maximum height for ( int i = 1; i < N; ++i) left[i] = min(arr[i], min(left[i - 1] + 1, (ull)i + 1)); // Maximum height at end is 1 right[N - 1] = min(arr[N - 1], (ull)1); // For each position calculate maximum height for ( int i = N - 2; i >= 0; --i) right[i] = min(arr[i], min(right[i + 1] + 1, N - i)); // Find minimum possible among calculated values ull tot[N]; for ( int i = 0; i < N; ++i) tot[i] = min(right[i], left[i]); // Find maximum height of pyramid ull max_ind = 0; for ( int i = 0; i < N; ++i) if (tot[i] > tot[max_ind]) max_ind = i; // Calculate cost of this pyramid ull cost = 0; ull height = tot[max_ind]; // Calculate cost of left half for ( int x = max_ind; x >= 0; --x) { cost += arr[x] - height; if (height > 0) --height; } // Calculate cost of right half height = tot[max_ind] - 1; for ( int x = max_ind + 1; x < N; ++x) { cost += arr[x] - height; if (height > 0) --height; } return cost; } // Driver code int main() { ull arr[] = {1, 2, 3, 4, 2, 1}; ull N = sizeof (arr)/ sizeof (arr[0]); cout << minPyramidCost(arr, N); return 0; } |
Java
// Java program to find minimum cost for // pyramid from given array import java.util.*; class GFG{ // Returns minimum cost to form a pyramid static int minPyramidCost( int arr[], int N) { // Store the maximum possible pyramid height int left[] = new int [N]; int right[] = new int [N]; // Maximum height at start is 1 left[ 0 ] = Math.min(arr[ 0 ], 1 ); // For each position calculate maximum height for ( int i = 1 ; i < N; ++i) left[i] = Math.min(arr[i], Math.min(left[i - 1 ] + 1 , i + 1 )); // Maximum height at end is 1 right[N - 1 ] = Math.min(arr[N - 1 ], 1 ); // For each position calculate maximum height for ( int i = N - 2 ; i >= 0 ; --i) right[i] = Math.min(arr[i], Math.min(right[i + 1 ] + 1 , N - i)); // Find minimum possible among // calculated values int tot[] = new int [N]; for ( int i = 0 ; i < N; ++i) tot[i] = Math.min(right[i], left[i]); // Find maximum height of pyramid int max_ind = 0 ; for ( int i = 0 ; i < N; ++i) if (tot[i] > tot[max_ind]) max_ind = i; // Calculate cost of this pyramid int cost = 0 ; int height = tot[max_ind]; // Calculate cost of left half for ( int x = max_ind; x >= 0 ; --x) { cost += arr[x] - height; if (height > 0 ) --height; } // Calculate cost of right half height = tot[max_ind] - 1 ; for ( int x = max_ind + 1 ; x < N; ++x) { cost += arr[x] - height; if (height > 0 ) --height; } return cost; } // Driver code public static void main(String[] args) { int arr[] = { 1 , 2 , 3 , 4 , 2 , 1 }; int N = arr.length; System.out.print(minPyramidCost(arr, N)); } } // This code is contributed by chitranayal |
Python3
# Program to find minimum cost for pyramid # from given array # Returns minimum cost to form a pyramid def minPyramidCost(arr: list , N): # Store the maximum possible pyramid height left = [ 0 ] * N right = [ 0 ] * N # Maximum height at start is 1 left[ 0 ] = min (arr[ 0 ], 1 ) # For each position calculate maximum height for i in range ( 1 , N): left[i] = min (arr[i], min (left[i - 1 ] + 1 , i + 1 )) # Maximum height at end is 1 right[N - 1 ] = min (arr[N - 1 ], 1 ) # For each position calculate maximum height for i in range (N - 2 , - 1 , - 1 ): right[i] = min (arr[i], min (right[i + 1 ] + 1 , N - i)) # Find minimum possible among calculated values tot = [ 0 ] * N for i in range (N): tot[i] = min (right[i], left[i]) # Find maximum height of pyramid max_ind = 0 for i in range (N): if tot[i] > tot[max_ind]: max_ind = i # Calculate cost of this pyramid cost = 0 height = tot[max_ind] # Calculate cost of left half for x in range (max_ind, - 1 , - 1 ): cost + = arr[x] - height if height > 0 : height - = 1 # Calculate cost of right half height = tot[max_ind] - 1 for x in range (max_ind + 1 , N): cost + = arr[x] - height if height > 0 : height - = 1 return cost # Driver Code if __name__ = = "__main__" : arr = [ 1 , 2 , 3 , 4 , 2 , 1 ] N = len (arr) print (minPyramidCost(arr, N)) # This code is contributed by # sanjeev2552 |
C#
// C# program to find minimum cost for // pyramid from given array using System; public class GFG { // Returns minimum cost to form a pyramid static int minPyramidCost( int [] arr, int N) { // Store the maximum possible pyramid height int [] left = new int [N]; int [] right = new int [N]; // Maximum height at start is 1 left[0] = Math.Min(arr[0], 1); // For each position calculate maximum height for ( int i = 1; i < N; ++i) left[i] = Math.Min(arr[i], Math.Min(left[i - 1] + 1, i + 1)); // Maximum height at end is 1 right[N - 1] = Math.Min(arr[N - 1], 1); // For each position calculate maximum height for ( int i = N - 2; i >= 0; --i) right[i] = Math.Min(arr[i], Math.Min(right[i + 1] + 1, N - i)); // Find minimum possible among // calculated values int [] tot = new int [N]; for ( int i = 0; i < N; ++i) tot[i] = Math.Min(right[i], left[i]); // Find maximum height of pyramid int max_ind = 0; for ( int i = 0; i < N; ++i) if (tot[i] > tot[max_ind]) max_ind = i; // Calculate cost of this pyramid int cost = 0; int height = tot[max_ind]; // Calculate cost of left half for ( int x = max_ind; x >= 0; --x) { cost += arr[x] - height; if (height > 0) --height; } // Calculate cost of right half height = tot[max_ind] - 1; for ( int x = max_ind + 1; x < N; ++x) { cost += arr[x] - height; if (height > 0) --height; } return cost; } // Driver code static public void Main () { int [] arr = { 1, 2, 3, 4, 2, 1 }; int N = arr.Length; Console.WriteLine(minPyramidCost(arr, N)); } } // This code is contributed by avanitrachhadiya2155 |
Javascript
<script> // Javascript program to find minimum cost for // pyramid from given array // Returns minimum cost to form a pyramid function minPyramidCost(arr,N) { // Store the maximum possible pyramid height let left = new Array(N); let right = new Array(N); // Maximum height at start is 1 left[0] = Math.min(arr[0], 1); // For each position calculate maximum height for (let i = 1; i < N; ++i) left[i] = Math.min(arr[i], Math.min(left[i - 1] + 1, i + 1)); // Maximum height at end is 1 right[N - 1] = Math.min(arr[N - 1], 1); // For each position calculate maximum height for (let i = N - 2; i >= 0; --i) right[i] = Math.min(arr[i], Math.min(right[i + 1] + 1, N - i)); // Find minimum possible among // calculated values let tot = new Array(N); for (let i = 0; i < N; ++i) tot[i] = Math.min(right[i], left[i]); // Find maximum height of pyramid let max_ind = 0; for (let i = 0; i < N; ++i) if (tot[i] > tot[max_ind]) max_ind = i; // Calculate cost of this pyramid let cost = 0; let height = tot[max_ind]; // Calculate cost of left half for (let x = max_ind; x >= 0; --x) { cost += arr[x] - height; if (height > 0) --height; } // Calculate cost of right half height = tot[max_ind] - 1; for (let x = max_ind + 1; x < N; ++x) { cost += arr[x] - height; if (height > 0) --height; } return cost; } // Driver code let arr=[1, 2, 3, 4, 2, 1 ]; let N = arr.length; document.write(minPyramidCost(arr, N)); // This code is contributed by rag2127. </script> |
4
Time Complexity: O(N)
Auxiliary Space: O(N)
This article is contributed by Aditya Kamath. If you like neveropen and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the neveropen main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!