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

📅  最后修改于: 2021-09-22 10:03:03             🧑  作者: Mango

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

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

任务是在将数组分成K部分后最小化值的总和。
例子:

方法:
蛮力解决方案是尝试所有可能的分区并取最小的整体。虽然这个解决方案在时间上是指数级的。在递归解决方案中,有许多重叠的子问题可以使用动态规划进行优化。
所以,我们可以形成一个基本的递归公式,计算每一个可能的解决方案并找到最好的解决方案。我们可以看到递归解决方案有许多重叠的子问题,我们可以使用动态规划来降低复杂度。
递归公式:
F(i, K) = { 所有值的最小值,使得 j < i [ max(Arr[i..j]) * (i – j + 1) – Sum(A[i…j] ] } + F( j, K-1)
自底向上的方法可用于首先计算子问题的值并存储它们。
这里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


Javascript


输出:
19

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程