📌  相关文章
📜  通过用它们的总和替换 K 个连续元素来最小化将数组减少到单个元素的成本

📅  最后修改于: 2021-09-17 07:23:31             🧑  作者: Mango

给定一个大小为N的数组arr[]和一个整数K ,任务是找到将给定数组减少到单个元素所需的最小成本,其中用它们的总和替换K个连续数组元素的成本等于K个连续元素。如果无法将给定数组缩减为单个元素,则打印-1

例子:

方法:该问题可以使用动态规划解决。以下是递推关系:

请按照以下步骤解决问题:

  • 如果(N – 1) % (K – 1) != 0然后打印-1
  • 初始化一个数组,比如 prefixSum[] 来存储给定数组的前缀和。
  • 初始化一个二维数组,比如dp[][] ,其中dp[i][j]存储合并区间[i, j] 中最大数组元素的最小成本。
  • 使用上述DP状态之间的关系填充DP表。
  • 最后,打印dp[0][N – 1] 的值

下面是上述方法的实现:

C++
// C++ program to implement
// the above approach
#include
using namespace std;
 
// Function to find the minimum cost
// to reduce given array to a single
// element by replacing consecutive
// K array elements
int minimumCostToMergeK(int arr[], int K, int N)
{
 
    // If (N - 1) is not
    // multiple of (K - 1)
    if ((N - 1) % (K - 1) != 0)
    {
        return -1;
    }
     
    // Store prefix sum of the array
    int prefixSum[N + 1] = {0};
 
    // Iterate over the range [1, N]
    for(int i = 1; i < (N + 1); i++)
    {
         
        // Update prefixSum[i]
        prefixSum[i] = (prefixSum[i - 1] + arr[i - 1]);
 
    }
 
    // dp[i][j]: Store minimum cost to
    // merge array elements interval [i, j]
    int dp[N][N];
    memset(dp, 0, sizeof(dp));
 
    // L: Stores length of interval [i, j]
    for(int L = K; L < (N + 1); L++)
    {
         
        // Iterate over each interval
        // [i, j] of length L in in [0, N]
        for(int i = 0; i < (N - L + 1); i++)
        {
             
            // Stores index of last element
            // of the interval [i, j]
            int j = i + L - 1;
 
            // If L is greater than K
            if (L > K)
            {
                int temp = INT_MAX;
                for(int x = i; x < j; x += K - 1)
                {
                    temp = min(temp, dp[i][x] +
                                     dp[x + 1][j]);
                }
                 
                // Update dp[i][j]
                dp[i][j] = temp;
            }
 
            // If (L - 1) is multiple of (K - 1)
            if ((L - 1) % (K - 1) == 0)
            {
                 
                // Update dp[i][j]
                dp[i][j] += (prefixSum[j + 1] -
                             prefixSum[i]);
            }
        }
    }
     
    // Return dp[0][N - 1]
    return dp[0][N - 1];
}
 
// Driver Code
int main()
{
    int arr[] = { 3, 5, 1, 2, 6 };
    int K = 3;
     
      // Stores length of arr
      int N = sizeof(arr) / sizeof(arr[0]);
       
    cout << minimumCostToMergeK(arr, K, N);
}
 
// This code is contributed by rag2127


Java
// Java program to implement
// the above approach
import java.util.*;
class GFG
{
 
  // Function to find the minimum cost
  // to reduce given array to a single
  // element by replacing consecutive
  // K array elements
  static int minimumCostToMergeK(int arr[], int K, int N)
  {
 
    // If (N - 1) is not
    // multiple of (K - 1)
    if ((N - 1) % (K - 1) != 0)
    {
      return -1;
    }
 
    // Store prefix sum of the array
    int []prefixSum = new int[N + 1];
 
    // Iterate over the range [1, N]
    for(int i = 1; i < (N + 1); i++)
    {
 
      // Update prefixSum[i]
      prefixSum[i] = (prefixSum[i - 1] + arr[i - 1]);
 
    }
 
    // dp[i][j]: Store minimum cost to
    // merge array elements interval [i, j]
    int [][]dp = new int[N][N];
 
    // L: Stores length of interval [i, j]
    for(int L = K; L < (N + 1); L++)
    {
 
      // Iterate over each interval
      // [i, j] of length L in in [0, N]
      for(int i = 0; i < (N - L + 1); i++)
      {
 
        // Stores index of last element
        // of the interval [i, j]
        int j = i + L - 1;
 
        // If L is greater than K
        if (L > K)
        {
          int temp = Integer.MAX_VALUE;
          for(int x = i; x < j; x += K - 1)
          {
            temp = Math.min(temp, dp[i][x] +
                            dp[x + 1][j]);
          }
 
          // Update dp[i][j]
          dp[i][j] = temp;
        }
 
        // If (L - 1) is multiple of (K - 1)
        if ((L - 1) % (K - 1) == 0)
        {
 
          // Update dp[i][j]
          dp[i][j] += (prefixSum[j + 1] -
                       prefixSum[i]);
        }
      }
    }
 
    // Return dp[0][N - 1]
    return dp[0][N - 1];
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int arr[] = { 3, 5, 1, 2, 6 };
    int K = 3;
 
    // Stores length of arr
    int N = arr.length;
    System.out.print(minimumCostToMergeK(arr, K, N));
  }
}
 
// This code is contributed by shikhasingrajput


Python3
# Python3 program to implement
# the above approach
 
# Function to find the minimum cost
# to reduce given array to a single
# element by replacing consecutive
# K array elements
def minimumCostToMergeK(arr, K): 
     
     
    # Stores length of arr
    N = len(arr)
 
    # If (N - 1) is not
    # multiple of (K - 1)
    if (N - 1) % (K - 1) != 0:
        return -1
     
    # Store prefix sum of the array
    prefixSum = [0] * (N + 1)
 
    # Iterate over the range [1, N]
    for i in range(1, N + 1):
 
        # Update prefixSum[i]
        prefixSum[i] = (prefixSum[i - 1]
                         + arr[i - 1])
 
    # dp[i][j]: Store minimum cost to
    # merge array elements interval [i, j]
    dp = [[0]*N for _ in range(N)]
 
    # L: Stores length of interval [i, j]
    for L in range(K, N + 1):
 
        # Iterate over each interval
        # [i, j] of length L in in [0, N]
        for i in range(N - L + 1):
 
            # Stores index of last element
            # of the interval [i, j]
            j = i + L - 1
 
            # If L is greater than K
            if L > K:
 
                # Update dp[i][j]
                dp[i][j] =(
                     min([dp[i][x] + dp[x + 1][j]
                     for x in range(i, j, K-1)]))
              
            # If (L - 1) is multiple of (K - 1)               
            if (L - 1) % (K - 1) == 0:
 
                # Update dp[i][j]
                dp[i][j] += (prefixSum[j + 1]
                              - prefixSum[i])
 
    # Return dp[0][N - 1]
    return dp[0][N-1]
 
if __name__ == "__main__":
    arr = [3, 5, 1, 2, 6]
    K = 3
    print(minimumCostToMergeK(arr, K))


C#
// C# program to implement
// the above approach
using System;
class GFG
{
 
  // Function to find the minimum cost
  // to reduce given array to a single
  // element by replacing consecutive
  // K array elements
  static int minimumCostToMergeK(int []arr, int K, int N)
  {
 
    // If (N - 1) is not
    // multiple of (K - 1)
    if ((N - 1) % (K - 1) != 0)
    {
      return -1;
    }
 
    // Store prefix sum of the array
    int []prefixSum = new int[N + 1];
 
    // Iterate over the range [1, N]
    for(int i = 1; i < (N + 1); i++)
    {
 
      // Update prefixSum[i]
      prefixSum[i] = (prefixSum[i - 1] + arr[i - 1]);
 
    }
 
    // dp[i,j]: Store minimum cost to
    // merge array elements interval [i, j]
    int [,]dp = new int[N,N];
 
    // L: Stores length of interval [i, j]
    for(int L = K; L < (N + 1); L++)
    {
 
      // Iterate over each interval
      // [i, j] of length L in in [0, N]
      for(int i = 0; i < (N - L + 1); i++)
      {
 
        // Stores index of last element
        // of the interval [i, j]
        int j = i + L - 1;
 
        // If L is greater than K
        if (L > K)
        {
          int temp = int.MaxValue;
          for(int x = i; x < j; x += K - 1)
          {
            temp = Math.Min(temp, dp[i, x] +
                            dp[x + 1, j]);
          }
 
          // Update dp[i,j]
          dp[i, j] = temp;
        }
 
        // If (L - 1) is multiple of (K - 1)
        if ((L - 1) % (K - 1) == 0)
        {
 
          // Update dp[i,j]
          dp[i, j] += (prefixSum[j + 1] -
                       prefixSum[i]);
        }
      }
    }
 
    // Return dp[0,N - 1]
    return dp[0, N - 1];
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
    int []arr = { 3, 5, 1, 2, 6 };
    int K = 3;
 
    // Stores length of arr
    int N = arr.Length;
    Console.Write(minimumCostToMergeK(arr, K, N));
  }
}
 
// This code is contributed by 29AjayKumar


Javascript


输出:
25

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