Minimum Cost To Merge Stones

Solution For Minimum Cost To Merge Stones

The Minimum Cost to Merge Stones problem is a dynamic programming problem on LeetCode. The problem statement is as follows:

You have a list of N stones, where each stone has a certain value. You want to merge the stones together into one pile, but you can only merge adjacent stones. The cost of merging two stones is the sum of their values. Find the minimum cost of merging all the stones into one pile.

To solve this problem, we can use a bottom-up dynamic programming approach. We can define a two-dimensional array dp, where dp[i][j] represents the minimum cost of merging stones i to j into one pile. The base case is when i = j, in which case the cost is 0.

We can then compute the values of dp[i][j] using the following recurrence relation:

dp[i][j] = min(dp[i][k] + dp[k+1][j] + sum(a[i..j])), i <= k < j

Here, sum(a[i..j]) represents the sum of values of stones i to j, inclusive. The recurrence relation essentially says that we consider all possible ways of splitting the stones into two sub-piles, merge each sub-pile recursively, and then merge the two resulting piles together at a cost equal to the sum of values of the stones in each pile.

We can compute the values of dp in increasing order of sub-pile sizes. Specifically, we can iterate over all possible sub-pile sizes L, and for each sub-pile size, iterate over all possible starting indices i for sub-piles of that size. For each starting index i, we can compute the corresponding ending index j and then compute the value of dp[i][j] using the recurrence relation.

Finally, the minimum cost of merging all the stones into one pile is given by dp[1][N]. The time complexity of this approach is O(N^3), since there are N^2 possible sub-piles and each sub-pile requires O(N) time to process.

Here’s the Python code to implement this approach:

def mergeStones(stones):
N = len(stones)
dp = [[0] * (N+1) for _ in range(N+1)] for L in range(2, N+1):
for i in range(1, N-L+2):
j = i + L – 1
dp[i][j] = float(‘inf’)
for k in range(i, j):
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j] + sum(stones[i-1:j]))
return dp[1][N] if dp[1][N] != float(‘inf’) else -1

Note that we initialize dp[i][j] to float(‘inf’) to indicate that the value has not yet been computed. We also check if dp[1][N] is equal to float(‘inf’) after computing all the values, since this indicates that it was not possible to merge all the stones into one pile.

Step by Step Implementation For Minimum Cost To Merge Stones

There is a stone pile with n stones. Each stone has a positive integer weight.

In each move, we can merge two adjacent stones into one stone with weight of their sum. The cost of this move is the sum of the weights of the stones merged. We merge the stones until there is only 1 stone left.

Return the minimum cost it takes to merge all the stones into 1 stone. If it is impossible to merge all the stones into 1 stone, return -1.

// n is the number of stones
// w is the array of stone weights

public int minimumCostToMergeStones(int n, int[] w) {
    // dp[i][j] is the minimum cost to merge stones from i to j into 1 stone
    int[][] dp = new int[n][n];
    // prefixSum[i] is the sum of stone weights from 0 to i
    int[] prefixSum = new int[n];
    
    // calculate prefix sums
    for (int i = 0; i < n; i++) {
        prefixSum[i] = w[i];
        if (i > 0) {
            prefixSum[i] += prefixSum[i - 1];
        }
    }
    
    // base case: dp[i][i] = 0 for all i
    // calculate dp for subproblems of increasing size
    for (int size = 2; size <= n; size++) {
        for (int i = 0; i <= n - size; i++) {
            int j = i + size - 1;
            dp[i][j] = Integer.MAX_VALUE;
            // try merging stones from i to k, then k+1 to j
            for (int k = i; k < j; k++) {
                dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k+1][j]);
            }
            // if all stones from i to j can be merged into 1 stone, 
            // update dp[i][j] with the cost of this merge
            if ((size == n - 1) && ((prefixSum[j] - prefixSum[i] + w[i]) % n == 0)) {
                dp[i][j] = dp[i][j] + (prefixSum[j] - prefixSum[i] + w[i]) / n;
            }
        }
    }
    // return the minimum cost to merge all stones into 1 stone, or -1 if it's impossible
    return (dp[0][n-1] == Integer.MAX_VALUE) ? -1 : dp[0][n-1];
}
There are a number of ways to solve this problem. One approach would be to use a priority queue to keep track of the costs of merging the stones. We would then repeatedly merge the two cheapest stones until there is only one stone left. The cost of merging two stones is the sum of the sizes of the stones.

import heapq 

def merge_stones(stones):
    # create a priority queue to store the stones 
    pq = []
    for stone in stones:
        heapq.heappush(pq, stone)
    
    # keep track of the cost of merging the stones 
    cost = 0
    
    # repeatedly merge the two cheapest stones until there is only one stone left 
    while len(pq) > 1:
        # get the two cheapest stones 
        stone1 = heapq.heappop(pq)
        stone2 = heapq.heappop(pq)
        
        # merge the two stones and add the cost to the total 
        cost += stone1 + stone2
        
        # add the merged stone back into the priority queue 
        heapq.heappush(pq, stone1 + stone2)
    
    return cost
There are a number of stones arranged in a row.  The i-th stone has a weight of stones[i].

Each turn, we pick up two adjacent stones and smash them together.  Suppose the stones have weights x and y with x <= y.  The result of this smash is:

If x == y, both stones are totally destroyed;
If x != y, the stone of weight x is totally destroyed, and the stone of weight y has new weight y-x.
At the end, there is at most 1 stone left.  Return the smallest possible weight of this stone (the weight is 0 if there are no stones left.)



function mergeStones(stones) {
    // base case: if there's only one stone left, return its weight
    if (stones.length === 1) {
        return stones[0];
    }
    
    // sort the stones from smallest to largest
    stones.sort((a, b) => a - b);
    
    // initialize a variable to keep track of the minimum cost
    let minCost = Infinity;
    
    // loop through all of the stones
    for (let i = 0; i < stones.length - 1; i++) {
        // initialize a variable to keep track of the current cost
        let cost = 0;
        
        // get the weight of the current stone
        let stone = stones[i];
        
        // loop through all of the stones that come after the current stone
        for (let j = i + 1; j < stones.length; j++) {
            // get the weight of the next stone
            let nextStone = stones[j];
            
            // if the weights of the stones are equal, both stones are destroyed
            if (stone === nextStone) {
                // remove the stones from the array
                stones.splice(i, 2);
                // reset the indices so we don't skip any stones
                i = -1;
                j = 0;
            } else {
                // otherwise, the stone of weight x is destroyed and the stone of weight y has new weight y-x
                stone = nextStone - stone;
                // remove the first stone from the array
                stones.splice(i, 1);
                // add the new stone to the array
                stones.splice(j, 0, stone);
                // reset the indices so we don't skip any stones
                i = -1;
                j = 0;
            }
            
            // add the cost of the current operation to the total cost
            cost += stone;
        }
        
        // update the minimum cost if necessary
        minCost = Math.min(minCost, cost);
    }
    
    // return the minimum cost
    return minCost;
}
There are a number of ways to solve this problem. One approach would be to use a priority queue to store the stones in order of increasing cost. Then, we can repeatedly remove the two cheapest stones and merge them together, keeping track of the total cost. Finally, we can return the cost of the merged stone.

#include 
#include 

int mergeStones(std::vector& stones) {
    // create a priority queue to store the stones
    std::priority_queue, std::greater> pq(stones.begin(), stones.end());
    
    // keep track of the total cost
    int cost = 0;
    
    // while there are more than 1 stone remaining
    while (pq.size() > 1) {
        // remove the two cheapest stones
        int stone1 = pq.top();
        pq.pop();
        int stone2 = pq.top();
        pq.pop();
        
        // merge the stones and add the cost to the total
        int mergedStone = stone1 + stone2;
        cost += mergedStone;
        
        // add the merged stone back into the priority queue
        pq.push(mergedStone);
    }
    
    // return the cost
    return cost;
}
There are a number of stones arranged in a row. Each stone has a weight associated with it. You would like to merge the stones into one stone by repeated merging of the stones. In each merge operation, you select any 2 stones that have the same weight, and merge them into a new stone that has the weight of the sum of the 2 stones' weights. The new stone is then placed back in the row.

You would like to find the minimum cost of merging all of the stones into a single stone. The cost of merging 2 stones is the sum of their weights.

class Solution { public int MergeStones(int[] stones, int K) { // TODO: Implement solution } }


Scroll to Top

Top 100 Leetcode Practice Problems In Java

Get 30% Off Instantly!
[gravityforms id="5" description="false" titla="false" ajax="true"]