给定一个数组arr[]和一个整数K 。任务是将数组分成K 个部分(子数组),使得所有子数组的值之和最小。
每个子数组的值定义为:
- 从该子数组中取最大值。
- 用最大值减去子数组的每个元素。
- 减去后取所有值的总和。
任务是在将数组分成K部分后最小化值的总和。
例子:
Input: arr[] = { 2, 9, 5, 4, 8, 3, 6 }, K = 2
Output: 19
Explanation:
The two groups are : {2} with max = 2 and {9, 5, 4, 8, 3, 6} with max=9,
sum of difference of first group = 2 – 2 = 0,
sum of difference of second group = (9-9) + (9-5) + (9-4) + (9-8) + (9-3) + (9-6) = 19
Input: arr[] = { 12, 20, 30, 14, 25}, K = 3
Output: 19
方法:
蛮力解决方案是尝试所有可能的分区并取最小的整体。虽然这个解决方案在时间上是指数级的。在递归解决方案中,有许多重叠的子问题可以使用动态规划进行优化。
所以,我们可以形成一个基本的递归公式,计算每一个可能的解决方案并找到最好的解决方案。我们可以看到递归解决方案有许多重叠的子问题,我们可以使用动态规划来降低复杂度。
递归公式:
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 现场工作专业课程和学生竞争性编程现场课程。