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. Task is to make a pyramid from given array of stones. In a pyramid, height of the stones start 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.

// 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;
}

Output:

4

This approach runs in O(N) time complexity.

This article is contributed by Aditya Kamath. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks 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.



My Personal Notes arrow_drop_up



Practice Tags :
Article Tags :
Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.

Recommended Posts:



3.7 Average Difficulty : 3.7/5.0
Based on 18 vote(s)






User Actions