给定一个包含N 个整数的列表,任务是将列表中的所有元素以可能的最小成本合并为一个。合并规则如下:
选择列表中任意两个相邻元素,其值为X和Y ,并将它们合并为一个值为(X + Y)的单个元素,总成本为(X + Y) 。
例子:
Input: arr[] = {1, 3, 7}
Output: 15
All possible ways of merging:
a) {1, 3, 7} (cost = 0) -> {4, 7} (cost = 0+4 = 4) -> 11 (cost = 4+11 = 15)
b) {1, 3, 7} (cost = 0) -> {1, 10} (cost = 0+10= 10) -> 11 (cost = 10+11 = 21)
Thus, ans = 15
Input: arr[] = {1, 2, 3, 4}
Output: 19
方法:这个问题可以用动态规划解决。让我们首先定义 DP 的状态。 DP[l][r]将是将子数组 arr[l…r]合并为一个的最小成本。
现在,让我们看一下递归关系:
DP[l][r] = min(S(l, l) + S(l + 1, r) + DP[l][l] + DP[l + 1][r], S(l, l + 1) + S(l + 2, r) + DP[l][l + 1] + DP[l + 2][r], …, S(l, r – 1) + S(r, r) + DP[l][r – 1] + DP[r][r]) = S(l, r) + min(DP[l][l] + DP[l + 1][r], DP[l][l + 1] + DP[l + 2][r], …, DP[l][r – 1] + DP[r][r])
where S(x, y) is the sum of all the elements of the subarray arr[x…y]
该方法的时间复杂度为O(N 3 ),因为总共有N * N个状态,并且每个状态通常需要O(N)时间来解决。
下面是上述方法的实现:
CPP
// C++ implementation of the approach
#include
using namespace std;
#define N 401
// To store the states of DP
int dp[N][N];
bool v[N][N];
// Function to return the minimum merge cost
int minMergeCost(int i, int j, int* arr)
{
// Base case
if (i == j)
return 0;
// If the state has been solved before
if (v[i][j])
return dp[i][j];
// Marking the state as solved
v[i][j] = 1;
int& x = dp[i][j];
// Reference to dp[i][j]
x = INT_MAX;
// To store the sum of all the
// elements in the subarray arr[i...j]
int tot = 0;
for (int k = i; k <= j; k++)
tot += arr[k];
// Loop to iterate the recurrence
for (int k = i + 1; k <= j; k++) {
x = min(x, tot + minMergeCost(i, k - 1, arr)
+ minMergeCost(k, j, arr));
}
// Returning the solved value
return x;
}
// Driver code
int main()
{
int arr[] = { 1, 3, 7 };
int n = sizeof(arr) / sizeof(int);
cout << minMergeCost(0, n - 1, arr);
return 0;
}
Java
// Java implementation of the approach
class GFG
{
static final int N = 401;
// To store the states of DP
static int [][]dp = new int[N][N];
static boolean [][]v = new boolean[N][N];
// Function to return the minimum merge cost
static int minMergeCost(int i, int j, int[] arr)
{
// Base case
if (i == j)
return 0;
// If the state has been solved before
if (v[i][j])
return dp[i][j];
// Marking the state as solved
v[i][j] = true;
int x = dp[i][j];
// Reference to dp[i][j]
x = Integer.MAX_VALUE;
// To store the sum of all the
// elements in the subarray arr[i...j]
int tot = 0;
for (int k = i; k <= j; k++)
tot += arr[k];
// Loop to iterate the recurrence
for (int k = i + 1; k <= j; k++)
{
x = Math.min(x, tot + minMergeCost(i, k - 1, arr)
+ minMergeCost(k, j, arr));
}
// Returning the solved value
return x;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 1, 3, 7 };
int n = arr.length;
System.out.print(minMergeCost(0, n - 1, arr));
}
}
// This code is contributed by PrinciRaj1992
Python3
# Python3 implementation of the approach
import sys
N = 401;
# To store the states of DP
dp = [[0 for i in range(N)] for j in range(N)];
v = [[False for i in range(N)] for j in range(N)];
# Function to return the minimum merge cost
def minMergeCost(i, j, arr):
# Base case
if (i == j):
return 0;
# If the state has been solved before
if (v[i][j]):
return dp[i][j];
# Marking the state as solved
v[i][j] = True;
x = dp[i][j];
# Reference to dp[i][j]
x = sys.maxsize;
# To store the sum of all the
# elements in the subarray arr[i...j]
tot = 0;
for k in range(i, j + 1):
tot += arr[k];
# Loop to iterate the recurrence
for k in range(i + 1, j + 1):
x = min(x, tot + minMergeCost(i, k - 1, arr) + \
minMergeCost(k, j, arr));
# Returning the solved value
return x;
# Driver code
if __name__ == '__main__':
arr = [ 1, 3, 7 ];
n = len(arr);
print(minMergeCost(0, n - 1, arr));
# This code is contributed by PrinciRaj1992
C#
// C# implementation of the approach
using System;
class GFG
{
static readonly int N = 401;
// To store the states of DP
static int [,]dp = new int[N, N];
static bool [,]v = new bool[N, N];
// Function to return the minimum merge cost
static int minMergeCost(int i, int j, int[] arr)
{
// Base case
if (i == j)
return 0;
// If the state has been solved before
if (v[i, j])
return dp[i, j];
// Marking the state as solved
v[i, j] = true;
int x = dp[i, j];
// Reference to dp[i,j]
x = int.MaxValue;
// To store the sum of all the
// elements in the subarray arr[i...j]
int tot = 0;
for (int k = i; k <= j; k++)
tot += arr[k];
// Loop to iterate the recurrence
for (int k = i + 1; k <= j; k++)
{
x = Math.Min(x, tot + minMergeCost(i, k - 1, arr)
+ minMergeCost(k, j, arr));
}
// Returning the solved value
return x;
}
// Driver code
public static void Main(String[] args)
{
int []arr = { 1, 3, 7 };
int n = arr.Length;
Console.Write(minMergeCost(0, n - 1, arr));
}
}
// This code is contributed by 29AjayKumar
Javascript
15
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。