Dada uma barra de comprimento de n polegadas e uma array de preços que inclui preços de todas as peças de tamanho menores que n. Determine o valor máximo que pode ser obtido cortando a haste e vendendo as peças. Por exemplo, se o comprimento da haste é 8 e os valores das diferentes peças são dados como a seguir, então o valor máximo que pode ser obtido é 22 (cortando duas peças de comprimentos 2 e 6) 

length   | 1   2   3   4   5   6   7   8  
--------------------------------------------
price    | 1   5   8   9  10  17  17  20

E se os preços forem os seguintes, então o valor máximo que pode ser obtido é 24 (cortando em oito pedaços de comprimento 1) 

length   | 1   2   3   4   5   6   7   8  
--------------------------------------------
price    | 3   5   8   9  10  17  17  20

Uma solução ingênua para esse problema é gerar todas as configurações de peças diferentes e encontrar a configuração de preço mais alto. Essa solução é exponencial em termos de complexidade de tempo. Vejamos como esse problema possui propriedades importantes de um problema de programação dinâmica (DP) e pode ser resolvido de forma eficiente usando a programação dinâmica.
1) Subestrutura Ótima: 
Podemos obter o melhor preço fazendo um corte em diferentes posições e comparando os valores obtidos após um corte. Podemos chamar recursivamente a mesma função para uma peça obtida após um corte.
Seja cutRod (n) o valor necessário (melhor preço possível) para uma barra de comprimento n. cutRod (n) pode ser escrito da seguinte maneira.
cutRod (n) = max (preço [i] + cutRod (ni-1)) para todo i em {0, 1 .. n-1}
2) Subproblemas sobrepostos 
A seguir está uma implementação recursiva simples do problema do corte da haste. 

A implementação simplesmente segue a estrutura recursiva mencionada acima.  

// A Naive recursive solution for Rod cutting problem
#include<stdio.h>
#include<limits.h>
 
// 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<n; i++)
         max_val = max(max_val, price[i] + cutRod(price, n-i-1));
 
   return max_val;
}
 
/* 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 %d", cutRod(arr, size));
    getchar();
    return 0;
}
// // 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<n; i++)
            max_val = Math.max(max_val,
                              price[i] + cutRod(price, n-i-1));
 
        return max_val;
    }
 
    /* 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 */
# 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'
// 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
// A Naive recursive solution for
// Rod cutting problem
 
/* Returns the best obtainable
   price for a rod of length n and
   price[] as prices of different
   pieces */
function cutRod( $price, $n)
{
 
    if ($n <= 0)
        return 0;
    $max_val = PHP_INT_MIN;
     
    // Recursively cut the rod in different
    // pieces and compare different
    // configurations
    for ($i = 0; $i < $n; $i++)
            $max_val = max($max_val, $price[$i] +
                    cutRod($price, $n - $i - 1));
     
    return $max_val;
}
 
    // Driver Code
    $arr = array(1, 5, 8, 9, 10, 17, 17, 20);
    $size =count($arr);
    echo "Maximum Obtainable Value is "
               , cutRod($arr, $size);
 
// This code is contributed anuj_67.
?>
<script>
 
    // A Naive recursive solution for
    // Rod cutting problem
     
    /* Returns the best obtainable
       price for a rod of length
       n and price[] as prices of
       different pieces */
    function cutRod(price, n)
    {
        if (n <= 0)
            return 0;
        let max_val = Number.MIN_VALUE;
   
        // Recursively cut the rod in
        // different pieces and compare
        // different configurations
        for (let i = 0; i < n; i++)
            max_val = Math.max(max_val, price[i] +
                        cutRod(price, n - i - 1));
   
        return max_val;
    }
     
    let arr = [1, 5, 8, 9, 10, 17, 17, 20];
    let size = arr.length;
    document.write("Maximum Obtainable Value is "+ cutRod(arr, size));
                                
</script>
Saída

O valor máximo obtido é 22

Considerando a implementação acima, a seguir está a árvore de recursão para uma haste de comprimento 4. 

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)

Na árvore de recursão parcial acima, cR (2) é resolvido duas vezes. Podemos ver que existem muitos subproblemas que são resolvidos continuamente. Como os mesmos subproblemas são chamados novamente, esse problema possui a propriedade Overlapping Subproblems. Portanto, o problema do corte da haste tem as duas propriedades (veja isto e aquilo ) de um problema de programação dinâmica. Como outros problemas típicos de Programação Dinâmica (DP) , recomputações dos mesmos subproblemas podem ser evitadas construindo um array temporário val [] de uma maneira ascendente. 

// A Dynamic Programming solution for Rod cutting problem
#include<stdio.h>
#include<limits.h>
 
// 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 %d", cutRod(arr, size));
    getchar();
    return 0;
}
// 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 */
# 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
// 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
// A Dynamic Programming solution for
// Rod cutting problem
 
/* Returns the best obtainable price
for a rod of length n and price[] as
prices of different pieces */
function cutRod( $price, $n)
{
    $val = array();
    $val[0] = 0;
    $i; $j;
     
    // Build the table val[] in bottom
    // up manner and return the last
    // entry from the table
    for ($i = 1; $i <= $n; $i++)
    {
        $max_val = PHP_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
$arr = array(1, 5, 8, 9, 10, 17, 17, 20);
$size = count($arr);
echo "Maximum Obtainable Value is ",
                      cutRod($arr, $size);
     
// This code is contributed by anuj_67.
?>
<script>
    // A Dynamic Programming solution
    // for Rod cutting problem
     
    /* Returns the best obtainable
       price for a rod of length n
       and price[] as prices of
       different pieces */
    function cutRod(price, n)
    {
        let val = new Array(n + 1);
        val[0] = 0;
  
        // Build the table val[] in
        // bottom up manner and return
        // the last entry from the table
        for (let i = 1; i<=n; i++)
        {
            let max_val = Number.MIN_VALUE;
            for (let j = 0; j < i; j++)
                max_val = Math.max(max_val, price[j] + val[i - j - 1]);
            val[i] = max_val;
        }
  
        return val[n];
    }
     
    let arr = [1, 5, 8, 9, 10, 17, 17, 20];
    let size = arr.length;
    document.write("Maximum Obtainable Value is " + cutRod(arr, size) + "n");
</script>
Saída
O valor máximo obtido é 22

A complexidade de tempo da implementação acima é O (n ^ 2), que é muito melhor do que a complexidade de tempo de pior caso da implementação Naive recursiva.

3) Usando a ideia de mochila ilimitada.

Esse problema é muito semelhante ao Problema da mochila sem limites, em que há várias ocorrências do mesmo item. Aqui estão os pedaços da vara.

Agora vou criar uma analogia entre a mochila sem limites e o problema do corte da haste. 


// CPP program for above approach
#include <iostream>
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 program for above approach
#include <stdio.h>
#include <stdlib.h>
 
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));
}
<script>
 
// Javascript program for above approach
 
// Global Array for
// the purpose of memoization.
let t = new Array(9);
for (var i = 0; i < t.length; i++) {
    t[i] = new Array(2);
}
 
// A recursive program, using ,
// memoization, to implement the
// rod cutting problem(Top-Down).
function un_kp(price, length, Max_len, 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]
            = Math.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 code
     
    let price = [ 1, 5, 8, 9, 10, 17, 17, 20 ];
    let n = price.length;
    let length = Array(n).fill(0);
    for (let i = 0; i < n; i++) {
        length[i] = i + 1;
    }
    let Max_len = n;
 
    // Function Call
    document.write("Maximum obtained value  is "
         + un_kp(price, length, n, Max_len));
 
</script>
Saída
O valor máximo obtido é 22

 
 

<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="374" src="https://www.youtube.com/embed/oqdttaJ_C6o?feature=oembed" width="665"></iframe>

Escreva comentários se encontrar algo incorreto ou se quiser compartilhar mais informações sobre o tópico discutido acima.