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

📅  最后修改于: 2021-09-17 07:32:13             🧑  作者: 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


Javascript


输出:
40

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