给定一个大小为N的数组arr[]和一个整数K ,任务是找到将给定数组减少到单个元素所需的最小成本,其中用它们的总和替换K个连续数组元素的成本等于K个连续元素。如果无法将给定数组缩减为单个元素,则打印-1 。
例子:
Input: arr[] = {3, 5, 1, 2, 6}, K = 3
Output: 25
Explanation:
Replacing {arr[1], arr[2], arr[3]} modifies arr[] = {3, 8, 6}. Cost = 8
Replacing {arr[0], arr[1], arr[2]} modifies arr[] = {17}. Cost = 17.
Therefore, the total cost to merge all the array elements into one = 8 + 17 = 25
Input: arr[] = {3, 2, 4, 1}, K = 3
Output: -1
Merging any K (=3) consecutive array elements left 2 elements in the array.
Therefore, the required output is -1.
方法:该问题可以使用动态规划解决。以下是递推关系:
Since the size of the array reduces by (K – 1) after every replacement operation,
dp[i][j] = min(dp[i][x], dp[x+1][j]), X = i + integer * (K – 1)
where, dp[i][j] stores the minimum cost to merge maximum number of array elements in the interval [i, j] with the left most element arr[i] always involved in merge if possible
请按照以下步骤解决问题:
- 如果(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 )