给定一个长度为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)可以编写如下。
对于{0,1 .. n-1}中的所有i,cutRod(n)= max(price [i] + cutRod(ni-1))
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 priceue 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 << "Maxmum 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 priceue 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("Maxmum obtained value is %d \n",
un_kp(price, length, n, Max_len));
}
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
Java脚本
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 priceue 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 << "Maxmum 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 priceue 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("Maxmum obtained value is %d \n",
un_kp(price, length, n, Max_len));
}
Maxmum obtained value is 22