📌  相关文章
📜  通过重复合并任何相邻元素来减少Array的最低成本

📅  最后修改于: 2021-04-17 08:21:06             🧑  作者: Mango

给定N个数字的数组arr [] 。我们可以将两个相邻的数字合并为一个,合并两个数字的成本等于两个值的总和。任务是找到合并所有数字的总最低成本。
例子:

方法:可以使用动态编程解决问题。步骤如下:

  1. 这个想法是将2个连续的数字合并到每个可能的索引i中,然后递归求解索引i的左右部分。
  2. 将上述步骤中合并两个数字的结果相加,并存储其中的最小值。
  3. 由于存在许多重复的子问题,因此我们使用备忘录将值存储在NxN矩阵中。
  4. 上述问题陈述的递归关系为:

5.现在dp [1] [N]将给出合并所有数字的最低总成本。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
  
// Function to find the total minimum
// cost of merging two consecutive numbers
int mergeTwoNumbers(vector& numbers)
{
    int len, i, j, k;
  
    // Find the size of numbers[]
    int n = numbers.size();
  
    // If array is empty, return 0
    if (numbers.size() == 0) {
        return 0;
    }
  
    // To store the prefix Sum of
    // numbers array numbers[]
    vector prefixSum(n + 1, 0);
  
    // Traverse numbers[] to find the
    // prefix sum
    for (int i = 1; i <= n; i++) {
        prefixSum[i] = prefixSum[i - 1]
                       + numbers[i - 1];
    }
  
    // dp table to memoised the value
    vector > dp(
        n + 1,
        vector(n + 1));
  
    // For single numbers cost is zero
    for (int i = 1; i <= n; i++) {
        dp[i][i] = 0;
    }
  
    // Iterate for length >= 1
    for (len = 2; len <= n; len++) {
  
        for (i = 1; i <= n - len + 1; i++) {
            j = i + len - 1;
  
            // Find sum in range [i..j]
            int sum = prefixSum[j]
                      - prefixSum[i - 1];
  
            // Initialise dp[i][j] to INT_MAX
            dp[i][j] = INT_MAX;
  
            // Iterate for all possible
            // K to find the minimum cost
            for (k = i; k < j; k++) {
  
                // Update the minimum sum
                dp[i][j]
                    = min(dp[i][j],
                          dp[i][k]
                              + dp[k + 1][j]
                              + sum);
            }
        }
    }
  
    // Return the final minimum cost
    return dp[1][n];
}
  
// Driver Code
int main()
{
    // Given set of numbers
    vector arr1 = { 6, 4, 4, 6 };
  
    // Function Call
    cout << mergeTwoNumbers(arr1)
         << endl;
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
class GFG{
  
// Function to find the total minimum
// cost of merging two consecutive numbers
static int mergeTwoNumbers(int []numbers)
{
    int len, i, j, k;
  
    // Find the size of numbers[]
    int n = numbers.length;
  
    // If array is empty, return 0
    if (numbers.length == 0)
    {
        return 0;
    }
  
    // To store the prefix Sum of
    // numbers array numbers[]
    int []prefixSum = new int[n + 1];
  
    // Traverse numbers[] to find the
    // prefix sum
    for (i = 1; i <= n; i++) 
    {
        prefixSum[i] = prefixSum[i - 1] +
                         numbers[i - 1];
    }
  
    // dp table to memoised the value
    int [][]dp = new int[n + 1][n + 1];
  
    // Iterate for length >= 1
    for (len = 2; len <= n; len++) 
    {
  
        for (i = 1; i <= n - len + 1; i++)
        {
            j = i + len - 1;
  
            // Find sum in range [i..j]
            int sum = prefixSum[j] - 
                      prefixSum[i - 1];
  
            // Initialise dp[i][j] to Integer.MAX_VALUE
            dp[i][j] = Integer.MAX_VALUE;
  
            // Iterate for all possible
            // K to find the minimum cost
            for (k = i; k < j; k++) 
            {
  
                // Update the minimum sum
                dp[i][j] = Math.min(dp[i][j], 
                                    dp[i][k] +
                                    dp[k + 1][j] + 
                                    sum);
            }
        }
    }
  
    // Return the final minimum cost
    return dp[1][n];
}
  
// Driver Code
public static void main(String[] args)
{
    // Given set of numbers
    int []arr1 = { 6, 4, 4, 6 };
  
    // Function Call
    System.out.print(mergeTwoNumbers(arr1) + "\n");
}
}
  
// This code is contributed by sapnasingh4991


Python3
# Python3 program for the above approach
import sys
  
# Function to find the total minimum
# cost of merging two consecutive numbers
def mergeTwoNumbers(numbers):
  
    # Find the size of numbers[]
    n = len(numbers)
  
    # If array is empty, return 0
    if (len(numbers) == 0):
        return 0
      
    # To store the prefix Sum of
    # numbers array numbers[]
    prefixSum = [0] * (n + 1)
  
    # Traverse numbers[] to find the
    # prefix sum
    for i in range(1, n + 1):
        prefixSum[i] = (prefixSum[i - 1] + 
                          numbers[i - 1])
      
    # dp table to memoised the value
    dp = [[0 for i in range(n + 1)] 
             for j in range(n + 1)] 
  
    # For single numbers cost is zero
    for i in range(1, n + 1):
        dp[i][i] = 0
      
    # Iterate for length >= 1
    for p in range(2, n + 1):
        for i in range(1, n - p + 2):
            j = i + p - 1
  
            # Find sum in range [i..j]
            sum = prefixSum[j] - prefixSum[i - 1]
  
            # Initialise dp[i][j] to _MAX
            dp[i][j] = sys.maxsize
  
            # Iterate for all possible
            # K to find the minimum cost
            for k in range(i, j):
  
                # Update the minimum sum
                dp[i][j] = min(dp[i][j], 
                              (dp[i][k] + 
                               dp[k + 1][j] + sum))
              
    # Return the final minimum cost
    return dp[1][n]
  
# Driver Code
  
# Given set of numbers
arr1 = [ 6, 4, 4, 6 ]
  
# Function call
print(mergeTwoNumbers(arr1))
  
# This code is contributed by sanjoy_62


C#
// C# program for the above approach 
using System;
class GFG{ 
  
// Function to find the total minimum 
// cost of merging two consecutive numbers 
static int mergeTwoNumbers(int []numbers) 
{ 
    int len, i, j, k; 
  
    // Find the size of numbers[] 
    int n = numbers.Length; 
  
    // If array is empty, return 0 
    if (numbers.Length == 0) 
    { 
        return 0; 
    } 
  
    // To store the prefix Sum of 
    // numbers array numbers[] 
    int []prefixSum = new int[n + 1]; 
  
    // Traverse numbers[] to find the 
    // prefix sum 
    for (i = 1; i <= n; i++) 
    { 
        prefixSum[i] = prefixSum[i - 1] + 
                         numbers[i - 1]; 
    } 
  
    // dp table to memoised the value 
    int [,]dp = new int[n + 1, n + 1]; 
  
    // Iterate for length >= 1 
    for (len = 2; len <= n; len++) 
    { 
  
        for (i = 1; i <= n - len + 1; i++) 
        { 
            j = i + len - 1; 
  
            // Find sum in range [i..j] 
            int sum = prefixSum[j] - 
                      prefixSum[i - 1]; 
  
            // Initialise dp[i,j] to int.MaxValue 
            dp[i,j] = int.MaxValue; 
  
            // Iterate for all possible 
            // K to find the minimum cost 
            for (k = i; k < j; k++) 
            { 
  
                // Update the minimum sum 
                dp[i, j] = Math.Min(dp[i, j], 
                                    dp[i, k] + 
                                    dp[k + 1, j] + 
                                    sum); 
            } 
        } 
    } 
  
    // Return the readonly minimum cost 
    return dp[1, n]; 
} 
  
// Driver Code 
public static void Main(String[] args) 
{ 
    // Given set of numbers 
    int []arr1 = { 6, 4, 4, 6 }; 
  
    // Function Call 
    Console.Write(mergeTwoNumbers(arr1) + "\n"); 
} 
} 
  
// This code is contributed by sapnasingh4991


输出:
40

时间复杂度: O(N 3 )
辅助空间复杂度: O(N 2 )