在给定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]至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
68