给定N根绳索,每根绳索都有一个与之相关的长度。一次,只有两条连续的小绳子系在末端形成一条大绳子和形成它们长度总和的成本。找出当所有绳索都系在一起形成一根绳索时的最小成本。
例子:
Input: arr[] = {7, 6, 8, 6, 1, 1}
Output: 68
{7, 6, 8, 6, 1, 1} – {7, 6, 8, 6, 2}, cost = 2
{7, 6, 8, 6, 2} – {7, 6, 8, 8}, cost = 8
{7, 6, 8, 8} – {13, 8, 8}, cost = 13
{13, 8, 8} – {13, 16}, cost = 16
{13, 16} – {29}, cost = 29
2 + 8 + 13 + 16 + 29 = 68
Input: arr[] = {10, 20, 30, 40}
Output: 190
方法:本文讨论了一个类似的问题,可以连接任何两条绳索,但在此问题中,只能连接连续的绳索。这个问题可以通过动态规划的矩阵链乘法技术来解决。
最优子结构:在第二个例子中,绳索可以连接为 (((10 + 20) + 30) + 40)
连接 10 和 20;成本 = 30;表达式变成 ((30 + 30) + 40)
连接 30 和 30;成本 = 90;表达式变成 (60 + 40)
连接60和40;成本 = 190,我们得到一根绳子
一个简单的解决方案是在所有可能的位置放置括号,然后计算每个段的成本并总结为总成本。这可以对所有有效的括号序列完成,最小值将是答案。
Given ropes of length r1, r2, r3 and r4.
The connection can be formed in the following ways:
(((r1 + r2) + r3) + r4) or
((r1 + (r2 + r3)) + r4) or
((r1 + r2) + (r3 + r4)) …
Total cost of the 1st way is = r4 + 2 * r3 + 3 * (r2 + r1)
因此,当放置括号集时,问题被划分为更小的子问题。因此,该问题具有最优子结构性质,并且可以使用递归轻松解决。
重叠子问题
(((r1 + r2) + r3) + r4)
and
((r1 + r2) + (r3 + r4))
both has a common part i.e. (r1 + r2)
所以解决方法如下:
- 预先计算不同区间的总和以节省计算时间。
- 如果我们希望 {arr[i] arr[i+1] …arr[k]} 和 {arr[k+1] arr[k+2] …arr[j]} 的两段连接,那么我们的成本将是
MinCost(i, k) + MinCost(k + 1, j) + sum(arr[i] to arr[j])
- 其中 MinCost(i, k) = 范围内的最小成本 (i, k) 和 sum(arr[i] to arr[j]) = 连接 (i, k) 和 (k + 1, j) 的绳段的成本)。我们可以将子问题存储在 dp 表中以节省计算时间。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// Function to return the minimum cost
// to connect the given ropes
int MinCost(int arr[], int n)
{
// dp[i][j] = minimum cost in range (i, j)
// sum[i][j] = sum of range (i, j)
int dp[n + 5][n + 5], sum[n + 5][n + 5];
// Initializing the sum table
memset(sum, 0, sizeof(0));
for (int i = 0; i < n; i++) {
int k = arr[i];
for (int j = i; j < n; j++) {
if (i == j)
sum[i][j] = k;
else {
k += arr[j];
sum[i][j] = k;
}
}
}
// Computing minimum cost for all
// the possible interval (i, j)
// Left range
for (int i = n - 1; i >= 0; i--) {
// Right range
for (int j = i; j < n; j++) {
dp[i][j] = INT_MAX;
// No cost for a single rope
if (i == j)
dp[i][j] = 0;
else {
for (int k = i; k < j; k++) {
dp[i][j] = min(dp[i][j],
dp[i][k] + dp[k + 1][j]
+ sum[i][j]);
}
}
}
}
return dp[0][n - 1];
}
// Driver code
int main()
{
int arr[] = { 7, 6, 8, 6, 1, 1 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << MinCost(arr, n);
return 0;
}
Java
// Java implementation of the approach
class GFG
{
// Function to return the minimum cost
// to connect the given ropes
static int MinCost(int arr[], int n)
{
// dp[i][j] = minimum cost in range (i, j)
// sum[i][j] = sum of range (i, j)
int [][]dp = new int[n + 5][n + 5];
int [][]sum = new int[n + 5][n + 5];
// Initializing the sum table
//memset(sum, 0, sizeof(0));
for (int i = 0; i < n; i++)
{
int k = arr[i];
for (int j = i; j < n; j++)
{
if (i == j)
sum[i][j] = k;
else
{
k += arr[j];
sum[i][j] = k;
}
}
}
// Computing minimum cost for all
// the possible interval (i, j)
// Left range
for (int i = n - 1; i >= 0; i--)
{
// Right range
for (int j = i; j < n; j++)
{
dp[i][j] = Integer.MAX_VALUE;
// No cost for a single rope
if (i == j)
dp[i][j] = 0;
else
{
for (int k = i; k < j; k++)
{
dp[i][j] = Math.min(dp[i][j],
dp[i][k] +
dp[k + 1][j] +
sum[i][j]);
}
}
}
}
return dp[0][n - 1];
}
// Driver code
public static void main(String []args)
{
int arr[] = { 7, 6, 8, 6, 1, 1 };
int n = arr.length;
System.out.println(MinCost(arr, n));
}
}
// This code is contributed by 29AjayKumar
Python3
# Python3 implementation of the approach
# Function to return the minimum cost
# to connect the given ropes
def MinCost(arr, n):
# dp[i][j] = minimum cost in range (i, j)
# sum[i][j] = sum of range (i, j)
dp = [[0 for i in range(n + 5)]
for i in range(n + 5)]
sum = [[0 for i in range(n + 5)]
for i in range(n + 5)]
for i in range(n):
k = arr[i]
for j in range(i, n):
if (i == j):
sum[i][j] = k
else:
k += arr[j]
sum[i][j] = k
# Computing minimum cost for all
# the possible interval (i, j)
# Left range
for i in range(n - 1, -1, -1):
# Right range
for j in range(i, n):
dp[i][j] = 10**9
# No cost for a single rope
if (i == j):
dp[i][j] = 0
else :
for k in range(i, j):
dp[i][j] = min(dp[i][j], dp[i][k] +
dp[k + 1][j] + sum[i][j])
return dp[0][n - 1]
# Driver code
arr = [7, 6, 8, 6, 1, 1]
n = len(arr)
print(MinCost(arr, n))
# This code is contributed
# by Mohit Kumar
C#
// C# implementation of the approach
using System;
class GFG
{
// Function to return the minimum cost
// to connect the given ropes
static int MinCost(int []arr, int n)
{
// dp[i,j] = minimum cost in range (i, j)
// sum[i,j] = sum of range (i, j)
int [,]dp = new int[n + 5, n + 5];
int [,]sum = new int[n + 5, n + 5];
// Initializing the sum table
//memset(sum, 0, sizeof(0));
for (int i = 0; i < n; i++)
{
int k = arr[i];
for (int j = i; j < n; j++)
{
if (i == j)
sum[i, j] = k;
else
{
k += arr[j];
sum[i, j] = k;
}
}
}
// Computing minimum cost for all
// the possible interval (i, j)
// Left range
for (int i = n - 1; i >= 0; i--)
{
// Right range
for (int j = i; j < n; j++)
{
dp[i, j] = int.MaxValue;
// No cost for a single rope
if (i == j)
dp[i, j] = 0;
else
{
for (int k = i; k < j; k++)
{
dp[i, j] = Math.Min(dp[i, j],
dp[i, k] +
dp[k + 1, j] +
sum[i, j]);
}
}
}
}
return dp[0, n - 1];
}
// Driver code
public static void Main(String []args)
{
int []arr = { 7, 6, 8, 6, 1, 1 };
int n = arr.Length;
Console.WriteLine(MinCost(arr, n));
}
}
// This code is contributed by Rajput-Ji
Javascript
68
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。