Thursday, July 4, 2024
HomeData ModellingDynamic ProgrammingPyramid form (increasing then decreasing) consecutive array using reduce operations

Pyramid form (increasing then decreasing) consecutive array using reduce operations

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.
Recommended Practice

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>


Output

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.neveropen.co.za or mail your article to review-team@neveropen.co.za. 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.

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

Dominic Rubhabha Wardslaus
Dominic Rubhabha Wardslaushttps://neveropen.dev
infosec,malicious & dos attacks generator, boot rom exploit philanthropist , wild hacker , game developer,
RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments