📌  相关文章
📜  在给定条件下将数组划分为K个子数组

📅  最后修改于: 2021-04-29 05:42:55             🧑  作者: Mango

给定一个数组arr []和一个整数K。任务是将数组划分为K个部分(子数组),以使所有子数组的值之和最小。

每个子数组的值定义为:

  • 从该子数组中获取最大值。
  • 用最大值减去子数组的每个元素。
  • 减去后取所有值的总和。

任务是在将数组划分为K个部分后,最小化值的总和。

例子:

方法:
暴力破解解决方案将尝试所有可能的分区,并采用最小的整体分区。尽管这种解决方案在时间上是指数级的。在递归解决方案中,有许多重叠的子问题可以使用动态编程进行优化。

因此,我们可以形成一个基本的递归公式,该公式可以计算所有可能的解决方案并找到最佳的解决方案。我们可以看到递归解决方案具有许多重叠的子问题,我们可以使用动态编程来降低复杂性。

递归公式:
F(i,K)= {所有值的最小值,使得j

自底向上方法可用于首先计算子问题的值并将其存储。

此处dp [i] [j]定义了如果数组从索引i开始并且具有j分区,则可以获取的最小值。

因此,问题的答案将是dp [0] [K] ,数组从0开始并具有K个分区。

下面是上述方法的实现:

C++
// C++ implementation of the above approach
  
#include 
using namespace std;
  
// Function to divide an array into k
// parts such that the sum of difference
// of every element with the maximum element
// of that part is minimum
int divideArray(int arr[], int n, int k)
{
    // Dp to store the values
    int dp[500][500] = { 0 };
  
    k -= 1;
  
    // Fill up the dp table
    for (int i = n - 1; i >= 0; i--) {
        for (int j = 0; j <= k; j++) {
            // Intitilize maximum value
            dp[i][j] = INT_MAX;
  
            // Max element and the sum
            int max_ = -1, sum = 0;
  
            // Run a loop from i to n
            for (int l = i; l < n; l++) {
                // Find the maximum number
                // from i to l and the sum
                // from i to l
                max_ = max(max_, arr[l]);
                sum += arr[l];
  
                // Find the sum of difference
                // of every element with the
                // maximum element
                int diff = (l - i + 1) * max_ - sum;
  
                // If the array can be divided
                if (j > 0)
                    dp[i][j]
                        = min(dp[i][j],
                              diff + dp[l + 1][j - 1]);
                else
                    dp[i][j] = diff;
            }
        }
    }
  
    // Returns the minimum sum
    // in K parts
    return dp[0][k];
}
  
// Driver code
int main()
{
    int arr[] = { 2, 9, 5, 4, 8, 3, 6 };
    int n = sizeof(arr) / sizeof(int);
    int k = 2;
  
    cout << divideArray(arr, n, k) << "\n";
  
    return 0;
}


Java
// Java implementation of the above approach 
class GFG
{
      
    // Function to divide an array into k 
    // parts such that the sum of difference 
    // of every element with the maximum element 
    // of that part is minimum 
    static int divideArray(int arr[], int n, int k) 
    { 
        // Dp to store the values 
        int dp[][] = new int[500][500]; 
          
        int i, j;
          
        for(i = 0; i < 500; i++)
            for(j = 0; j < 500; j++)
                dp[i][j] = 0;
                  
        k -= 1; 
      
        // Fill up the dp table 
        for (i = n - 1; i >= 0; i--) 
        { 
            for (j = 0; j <= k; j++) 
            { 
                  
                // Intitilize maximum value 
                dp[i][j] = Integer.MAX_VALUE; 
      
                // Max element and the sum 
                int max_ = -1, sum = 0; 
      
                // Run a loop from i to n 
                for (int l = i; l < n; l++)
                { 
                    // Find the maximum number 
                    // from i to l and the sum 
                    // from i to l 
                    max_ = Math.max(max_, arr[l]); 
                    sum += arr[l]; 
      
                    // Find the sum of difference 
                    // of every element with the 
                    // maximum element 
                    int diff = (l - i + 1) * max_ - sum; 
      
                    // If the array can be divided 
                    if (j > 0) 
                        dp[i][j] = Math.min(dp[i][j], diff + 
                                            dp[l + 1][j - 1]); 
                    else
                        dp[i][j] = diff; 
                } 
            } 
        } 
      
        // Returns the minimum sum 
        // in K parts 
        return dp[0][k]; 
    } 
      
    // Driver code 
    public static void main (String[] args)
    { 
        int arr[] = { 2, 9, 5, 4, 8, 3, 6 }; 
        int n = arr.length; 
        int k = 2; 
      
        System.out.println(divideArray(arr, n, k)); 
    } 
}
  
// This code is contributed by AnkitRai01


Python3
# Python3 implementation of the above approach
  
# Function to divide an array into k
# parts such that the summ of difference
# of every element with the maximum element
# of that part is minimum
def divideArray(arr, n, k):
      
    # Dp to store the values
    dp = [[0 for i in range(500)] 
             for i in range(500)]
  
    k -= 1
  
    # Fill up the dp table
    for i in range(n - 1, -1, -1):
        for j in range(0, k + 1):
              
            # Intitilize maximum value
            dp[i][j] = 10**9
  
            # Max element and the summ
            max_ = -1
            summ = 0
  
            # Run a loop from i to n
            for l in range(i, n):
                  
                # Find the maximum number
                # from i to l and the summ
                # from i to l
                max_ = max(max_, arr[l])
                summ += arr[l]
  
                # Find the summ of difference
                # of every element with the
                # maximum element
                diff = (l - i + 1) * max_ - summ
  
                # If the array can be divided
                if (j > 0):
                    dp[i][j]= min(dp[i][j], diff + 
                                  dp[l + 1][j - 1])
                else:
                    dp[i][j] = diff
  
    # Returns the minimum summ
    # in K parts
    return dp[0][k]
  
# Driver code
arr = [2, 9, 5, 4, 8, 3, 6]
n = len(arr)
k = 2
  
print(divideArray(arr, n, k))
  
# This code is contributed by Mohit Kumar


C#
// C# implementation of above approach
using System;
  
class GFG
{
      
    // Function to divide an array into k 
    // parts such that the sum of difference 
    // of every element with the maximum element 
    // of that part is minimum 
    static int divideArray(int []arr, int n, int k) 
    { 
        // Dp to store the values 
        int [,]dp = new int[500, 500]; 
          
        int i, j;
          
        for(i = 0; i < 500; i++)
            for(j = 0; j < 500; j++)
                dp[i, j] = 0;
                  
        k -= 1; 
      
        // Fill up the dp table 
        for (i = n - 1; i >= 0; i--) 
        { 
            for (j = 0; j <= k; j++) 
            { 
                  
                // Intitilize maximum value 
                dp[i, j] = int.MaxValue; 
      
                // Max element and the sum 
                int max_ = -1, sum = 0; 
      
                // Run a loop from i to n 
                for (int l = i; l < n; l++)
                { 
                    // Find the maximum number 
                    // from i to l and the sum 
                    // from i to l 
                    max_ = Math.Max(max_, arr[l]); 
                    sum += arr[l]; 
      
                    // Find the sum of difference 
                    // of every element with the 
                    // maximum element 
                    int diff = (l - i + 1) * max_ - sum; 
      
                    // If the array can be divided 
                    if (j > 0) 
                        dp[i, j] = Math.Min(dp[i, j], diff + 
                                            dp[l + 1, j - 1]); 
                    else
                        dp[i, j] = diff; 
                } 
            } 
        } 
      
        // Returns the minimum sum 
        // in K parts 
        return dp[0, k]; 
    } 
      
    // Driver code 
    public static void Main (String[] args)
    { 
        int []arr = { 2, 9, 5, 4, 8, 3, 6 }; 
        int n = arr.Length; 
        int k = 2; 
      
        Console.WriteLine(divideArray(arr, n, k)); 
    } 
}
  
// This code is contributed by 29AjayKumar


输出:
19