给定一根长度为 n 英寸的杆和一系列价格,其中包括所有尺寸小于 n 的价格。确定通过切割杆并出售碎片可获得的最大值。例如,如果杆的长度为 8,并且不同部分的值如下所示,则可获得的最大值为 22(通过切割长度为 2 和 6 的两段)
length | 1 2 3 4 5 6 7 8
--------------------------------------------
price | 1 5 8 9 10 17 17 20
并且如果价格如下,那么最大可获取值是24(切8个长度1)
length | 1 2 3 4 5 6 7 8
--------------------------------------------
price | 3 5 8 9 10 17 17 20
这个问题的一个简单的解决方案是生成不同部分的所有配置并找到价格最高的配置。该解决方案在时间复杂度方面呈指数级增长。让我们看看这个问题如何拥有动态规划 (DP) 问题的两个重要属性,并且可以使用动态规划有效地解决。
1) 最优子结构:
我们可以通过在不同位置进行削减并比较削减后获得的值来获得最佳价格。我们可以为切割后获得的一块递归调用相同的函数。
令 cutRod(n) 是长度为 n 的杆所需的(最佳可能价格)值。 cutRod(n) 可以写成如下。
cutRod(n) = max(price[i] + cutRod(ni-1)) 对于 {0, 1 .. n-1} 中的所有 i
2) 重叠子问题
下面是杆切割问题的简单递归实现。
实现只是简单地遵循上面提到的递归结构。
C++
// A Naive recursive solution for Rod cutting problem
#include
#include
// A utility function to get the maximum of two integers
int max(int a, int b) { return (a > b)? a : b;}
/* Returns the best obtainable price for a rod of length n and
price[] as prices of different pieces */
int cutRod(int price[], int n)
{
if (n <= 0)
return 0;
int max_val = INT_MIN;
// Recursively cut the rod in different pieces and compare different
// configurations
for (int i = 0; i
Java
// // A Naive recursive solution for Rod cutting problem
class RodCutting
{
/* Returns the best obtainable price for a rod of length
n and price[] as prices of different pieces */
static int cutRod(int price[], int n)
{
if (n <= 0)
return 0;
int max_val = Integer.MIN_VALUE;
// Recursively cut the rod in different pieces and
// compare different configurations
for (int i = 0; i
Python
# A Naive recursive solution
# for Rod cutting problem
import sys
# A utility function to get the
# maximum of two integers
def max(a, b):
return a if (a > b) else b
# Returns the best obtainable price for a rod of length n
# and price[] as prices of different pieces
def cutRod(price, n):
if(n <= 0):
return 0
max_val = -sys.maxsize-1
# Recursively cut the rod in different pieces
# and compare different configurations
for i in range(0, n):
max_val = max(max_val, price[i] +
cutRod(price, n - i - 1))
return max_val
# Driver code
arr = [1, 5, 8, 9, 10, 17, 17, 20]
size = len(arr)
print("Maximum Obtainable Value is", cutRod(arr, size))
# This code is contributed by 'Smitha Dinesh Semwal'
C#
// A Naive recursive solution for
// Rod cutting problem
using System;
class GFG {
/* Returns the best obtainable
price for a rod of length
n and price[] as prices of
different pieces */
static int cutRod(int []price, int n)
{
if (n <= 0)
return 0;
int max_val = int.MinValue;
// Recursively cut the rod in
// different pieces and compare
// different configurations
for (int i = 0; i < n; i++)
max_val = Math.Max(max_val, price[i] +
cutRod(price, n - i - 1));
return max_val;
}
// Driver Code
public static void Main()
{
int []arr = new int[] {1, 5, 8, 9, 10, 17, 17, 20};
int size = arr.Length;
Console.WriteLine("Maximum Obtainable Value is "+
cutRod(arr, size));
}
}
// This code is contributed by Sam007
PHP
Javascript
C++
// A Dynamic Programming solution for Rod cutting problem
#include
#include
// A utility function to get the maximum of two integers
int max(int a, int b) { return (a > b)? a : b;}
/* Returns the best obtainable price for a rod of length n and
price[] as prices of different pieces */
int cutRod(int price[], int n)
{
int val[n+1];
val[0] = 0;
int i, j;
// Build the table val[] in bottom up manner and return the last entry
// from the table
for (i = 1; i<=n; i++)
{
int max_val = INT_MIN;
for (j = 0; j < i; j++)
max_val = max(max_val, price[j] + val[i-j-1]);
val[i] = max_val;
}
return val[n];
}
/* Driver program to test above functions */
int main()
{
int arr[] = {1, 5, 8, 9, 10, 17, 17, 20};
int size = sizeof(arr)/sizeof(arr[0]);
printf("Maximum Obtainable Value is %dn", cutRod(arr, size));
getchar();
return 0;
}
Java
// A Dynamic Programming solution for Rod cutting problem
class RodCutting
{
/* Returns the best obtainable price for a rod of
length n and price[] as prices of different pieces */
static int cutRod(int price[],int n)
{
int val[] = new int[n+1];
val[0] = 0;
// Build the table val[] in bottom up manner and return
// the last entry from the table
for (int i = 1; i<=n; i++)
{
int max_val = Integer.MIN_VALUE;
for (int j = 0; j < i; j++)
max_val = Math.max(max_val,
price[j] + val[i-j-1]);
val[i] = max_val;
}
return val[n];
}
/* Driver program to test above functions */
public static void main(String args[])
{
int arr[] = new int[] {1, 5, 8, 9, 10, 17, 17, 20};
int size = arr.length;
System.out.println("Maximum Obtainable Value is " +
cutRod(arr, size));
}
}
/* This code is contributed by Rajat Mishra */
Python
# A Dynamic Programming solution for Rod cutting problem
INT_MIN = -32767
# Returns the best obtainable price for a rod of length n and
# price[] as prices of different pieces
def cutRod(price, n):
val = [0 for x in range(n+1)]
val[0] = 0
# Build the table val[] in bottom up manner and return
# the last entry from the table
for i in range(1, n+1):
max_val = INT_MIN
for j in range(i):
max_val = max(max_val, price[j] + val[i-j-1])
val[i] = max_val
return val[n]
# Driver program to test above functions
arr = [1, 5, 8, 9, 10, 17, 17, 20]
size = len(arr)
print("Maximum Obtainable Value is " + str(cutRod(arr, size)))
# This code is contributed by Bhavya Jain
C#
// A Dynamic Programming solution
// for Rod cutting problem
using System;
class GFG {
/* Returns the best obtainable
price for a rod of length n
and price[] as prices of
different pieces */
static int cutRod(int []price,int n)
{
int []val = new int[n + 1];
val[0] = 0;
// Build the table val[] in
// bottom up manner and return
// the last entry from the table
for (int i = 1; i<=n; i++)
{
int max_val = int.MinValue;
for (int j = 0; j < i; j++)
max_val = Math.Max(max_val,
price[j] + val[i - j - 1]);
val[i] = max_val;
}
return val[n];
}
// Driver Code
public static void Main()
{
int []arr = new int[] {1, 5, 8, 9, 10, 17, 17, 20};
int size = arr.Length;
Console.WriteLine("Maximum Obtainable Value is " +
cutRod(arr, size));
}
}
// This code is contributed by Sam007
PHP
Javascript
C++
// CPP program for above approach
#include
using namespace std;
// Global Array for
// the purpose of memoization.
int t[9][9];
// A recursive program, using ,
// memoization, to implement the
// rod cutting problem(Top-Down).
int un_kp(int price[], int length[],
int Max_len, int n)
{
// The maximum price will be zero,
// when either the length of the rod
// is zero or price is zero.
if (n == 0 || Max_len == 0)
{
return 0;
}
// If the length of the rod is less
// than the maximum length, Max_lene will
// consider it.Now depending
// upon the profit,
// either Max_lene we will take
// it or discard it.
if (length[n - 1] <= Max_len)
{
t[n][Max_len]
= max(price[n - 1]
+ un_kp(price, length,
Max_len - length[n - 1], n),
un_kp(price, length, Max_len, n - 1));
}
// If the length of the rod is
// greater than the permitted size,
// Max_len we will not consider it.
else
{
t[n][Max_len]
= un_kp(price, length,
Max_len, n - 1);
}
// Max_lene Max_lenill return the maximum
// value obtained, Max_lenhich is present
// at the nth roMax_len and Max_lenth column.
return t[n][Max_len];
}
/* Driver program to
test above functions */
int main()
{
int price[] = { 1, 5, 8, 9, 10, 17, 17, 20 };
int n = sizeof(price) / sizeof(price[0]);
int length[n];
for (int i = 0; i < n; i++) {
length[i] = i + 1;
}
int Max_len = n;
// Function Call
cout << "Maximum obtained value is "
<< un_kp(price, length, n, Max_len) << endl;
}
C
// C program for above approach
#include
#include
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Global Array for the
// purpose of memoization.
int t[9][9];
// A recursive program, using ,
// memoization, to implement the
// rod cutting problem(Top-Down).
int un_kp(int price[], int length[],
int Max_len, int n)
{
// The maximum price will be zero,
// when either the length of the rod
// is zero or price is zero.
if (n == 0 || Max_len == 0)
{
return 0;
}
// If the length of the rod is less
// than the maximum length, Max_lene
// will consider it.Now depending
// upon the profit,
// either Max_lene we will take it
// or discard it.
if (length[n - 1] <= Max_len)
{
t[n][Max_len]
= max(price[n - 1]
+ un_kp(price, length,
Max_len - length[n - 1], n),
un_kp(price, length, Max_len, n - 1));
}
// If the length of the rod is greater
// than the permitted size, Max_len
// we will not consider it.
else
{
t[n][Max_len]
= un_kp(price, length,
Max_len, n - 1);
}
// Max_lene Max_lenill return
// the maximum value obtained,
// Max_lenhich is present at the
// nth roMax_len and Max_lenth column.
return t[n][Max_len];
}
/* Driver program to test above functions */
int main()
{
int price[] = { 1, 5, 8, 9, 10, 17, 17, 20 };
int n = sizeof(price) / sizeof(price[0]);
int length[n];
for (int i = 0; i < n; i++)
{
length[i] = i + 1;
}
int Max_len = n;
// Function Call
printf("Maximum obtained value is %d \n",
un_kp(price, length, n, Max_len));
}
Javascript
Maximum Obtainable Value is 22n
考虑到上述实现,以下是长度为 4 的 Rod 的递归树。
cR() ---> cutRod()
cR(4)
/ /
/ /
cR(3) cR(2) cR(1) cR(0)
/ | / |
/ | / |
cR(2) cR(1) cR(0) cR(1) cR(0) cR(0)
/ | |
/ | |
cR(1) cR(0) cR(0) cR(0)
/
/
CR(0)
在上面的部分递归树中,cR(2) 求解了两次。我们可以看到有很多子问题被一次又一次地解决了。由于再次调用相同的子问题,此问题具有重叠子问题的属性。因此,棒切割问题具有动态规划问题的两个性质(见这个和这个)。与其他典型的动态规划 (DP) 问题一样,可以通过以自底向上的方式构造临时数组 val[] 来避免对相同子问题的重新计算。
C++
// A Dynamic Programming solution for Rod cutting problem
#include
#include
// A utility function to get the maximum of two integers
int max(int a, int b) { return (a > b)? a : b;}
/* Returns the best obtainable price for a rod of length n and
price[] as prices of different pieces */
int cutRod(int price[], int n)
{
int val[n+1];
val[0] = 0;
int i, j;
// Build the table val[] in bottom up manner and return the last entry
// from the table
for (i = 1; i<=n; i++)
{
int max_val = INT_MIN;
for (j = 0; j < i; j++)
max_val = max(max_val, price[j] + val[i-j-1]);
val[i] = max_val;
}
return val[n];
}
/* Driver program to test above functions */
int main()
{
int arr[] = {1, 5, 8, 9, 10, 17, 17, 20};
int size = sizeof(arr)/sizeof(arr[0]);
printf("Maximum Obtainable Value is %dn", cutRod(arr, size));
getchar();
return 0;
}
Java
// A Dynamic Programming solution for Rod cutting problem
class RodCutting
{
/* Returns the best obtainable price for a rod of
length n and price[] as prices of different pieces */
static int cutRod(int price[],int n)
{
int val[] = new int[n+1];
val[0] = 0;
// Build the table val[] in bottom up manner and return
// the last entry from the table
for (int i = 1; i<=n; i++)
{
int max_val = Integer.MIN_VALUE;
for (int j = 0; j < i; j++)
max_val = Math.max(max_val,
price[j] + val[i-j-1]);
val[i] = max_val;
}
return val[n];
}
/* Driver program to test above functions */
public static void main(String args[])
{
int arr[] = new int[] {1, 5, 8, 9, 10, 17, 17, 20};
int size = arr.length;
System.out.println("Maximum Obtainable Value is " +
cutRod(arr, size));
}
}
/* This code is contributed by Rajat Mishra */
Python
# A Dynamic Programming solution for Rod cutting problem
INT_MIN = -32767
# Returns the best obtainable price for a rod of length n and
# price[] as prices of different pieces
def cutRod(price, n):
val = [0 for x in range(n+1)]
val[0] = 0
# Build the table val[] in bottom up manner and return
# the last entry from the table
for i in range(1, n+1):
max_val = INT_MIN
for j in range(i):
max_val = max(max_val, price[j] + val[i-j-1])
val[i] = max_val
return val[n]
# Driver program to test above functions
arr = [1, 5, 8, 9, 10, 17, 17, 20]
size = len(arr)
print("Maximum Obtainable Value is " + str(cutRod(arr, size)))
# This code is contributed by Bhavya Jain
C#
// A Dynamic Programming solution
// for Rod cutting problem
using System;
class GFG {
/* Returns the best obtainable
price for a rod of length n
and price[] as prices of
different pieces */
static int cutRod(int []price,int n)
{
int []val = new int[n + 1];
val[0] = 0;
// Build the table val[] in
// bottom up manner and return
// the last entry from the table
for (int i = 1; i<=n; i++)
{
int max_val = int.MinValue;
for (int j = 0; j < i; j++)
max_val = Math.Max(max_val,
price[j] + val[i - j - 1]);
val[i] = max_val;
}
return val[n];
}
// Driver Code
public static void Main()
{
int []arr = new int[] {1, 5, 8, 9, 10, 17, 17, 20};
int size = arr.Length;
Console.WriteLine("Maximum Obtainable Value is " +
cutRod(arr, size));
}
}
// This code is contributed by Sam007
PHP
Javascript
Maximum Obtainable Value is 22n
上述实现的时间复杂度为O(n^2),比Naive Recursive实现的最坏情况时间复杂度要好很多。
3)利用无界背包的思想。
这个问题与无界背包问题非常相似,其中同一项目多次出现。这里是杆的碎片。
现在我将在无界背包和杆切割问题之间进行类比。
C++
// CPP program for above approach
#include
using namespace std;
// Global Array for
// the purpose of memoization.
int t[9][9];
// A recursive program, using ,
// memoization, to implement the
// rod cutting problem(Top-Down).
int un_kp(int price[], int length[],
int Max_len, int n)
{
// The maximum price will be zero,
// when either the length of the rod
// is zero or price is zero.
if (n == 0 || Max_len == 0)
{
return 0;
}
// If the length of the rod is less
// than the maximum length, Max_lene will
// consider it.Now depending
// upon the profit,
// either Max_lene we will take
// it or discard it.
if (length[n - 1] <= Max_len)
{
t[n][Max_len]
= max(price[n - 1]
+ un_kp(price, length,
Max_len - length[n - 1], n),
un_kp(price, length, Max_len, n - 1));
}
// If the length of the rod is
// greater than the permitted size,
// Max_len we will not consider it.
else
{
t[n][Max_len]
= un_kp(price, length,
Max_len, n - 1);
}
// Max_lene Max_lenill return the maximum
// value obtained, Max_lenhich is present
// at the nth roMax_len and Max_lenth column.
return t[n][Max_len];
}
/* Driver program to
test above functions */
int main()
{
int price[] = { 1, 5, 8, 9, 10, 17, 17, 20 };
int n = sizeof(price) / sizeof(price[0]);
int length[n];
for (int i = 0; i < n; i++) {
length[i] = i + 1;
}
int Max_len = n;
// Function Call
cout << "Maximum obtained value is "
<< un_kp(price, length, n, Max_len) << endl;
}
C
// C program for above approach
#include
#include
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Global Array for the
// purpose of memoization.
int t[9][9];
// A recursive program, using ,
// memoization, to implement the
// rod cutting problem(Top-Down).
int un_kp(int price[], int length[],
int Max_len, int n)
{
// The maximum price will be zero,
// when either the length of the rod
// is zero or price is zero.
if (n == 0 || Max_len == 0)
{
return 0;
}
// If the length of the rod is less
// than the maximum length, Max_lene
// will consider it.Now depending
// upon the profit,
// either Max_lene we will take it
// or discard it.
if (length[n - 1] <= Max_len)
{
t[n][Max_len]
= max(price[n - 1]
+ un_kp(price, length,
Max_len - length[n - 1], n),
un_kp(price, length, Max_len, n - 1));
}
// If the length of the rod is greater
// than the permitted size, Max_len
// we will not consider it.
else
{
t[n][Max_len]
= un_kp(price, length,
Max_len, n - 1);
}
// Max_lene Max_lenill return
// the maximum value obtained,
// Max_lenhich is present at the
// nth roMax_len and Max_lenth column.
return t[n][Max_len];
}
/* Driver program to test above functions */
int main()
{
int price[] = { 1, 5, 8, 9, 10, 17, 17, 20 };
int n = sizeof(price) / sizeof(price[0]);
int length[n];
for (int i = 0; i < n; i++)
{
length[i] = i + 1;
}
int Max_len = n;
// Function Call
printf("Maximum obtained value is %d \n",
un_kp(price, length, n, Max_len));
}
Javascript
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。