Taglio delle aste

Nel problema del taglio delle aste si vuole cercare il massimo guadagno ottenibile dalla vendita di pezzi ricavati dal taglio di un'asta lunga , i cui prezzi dipendono dalla lunghezza venduta.

Per esempio se e conviene tagliare l'asta in pezzi da o invece che perchè si guadagna invece che .

Sottostruttura ottima

Un'asta lunga può essere tagliata o meno in ogni posizione , totalizzando tagli e quindi portando la complessità a .

Il ricavo per l'asta sarà quindi definito ricorsivamente come: dove è il ricavo della prima parte non tagliata ulteriormente e è il maggior ricavo sul resto dell'asta.

Per il problema si dice che valga la proprietà di sottostruttura ottima perchè la soluzione ottima cercata, in questo caso , è esprimibile da combinazioni di soluzione ottime di sottoproblemi.

Ricorsione

L'algoritmo che se ne ricava

cut_rod(p, n)
  if n == 0
    return 0
  else
    q = -1
    for i = 1 to n
      q = max(q, p[i] + cut_rod(p, n-i))
    return q

avrà complessità: che diventa per induzione su :

  • Caso base, per :
  • Passo induttivo assumendo che :

Top-down

cut_rod(p, n)
  r = {}
  for i = 0 to n
    r[i] = -1
  return cut_rod_aux(p, n, r)

cut_rod_aux(p, j, r)
  if r[j] < 0
    if j == 0
      r[j] = 0
    else
      q = -1
      for i = 1 to j
        q = max(q, p[i] + cut_rod_aux(p, j - i, r))
      r[j] = q
  return r[j]

La complessità si può ricavare come: perchè al diminuire di j i valori r[j-i] sono già stati calcolati.

Bottom-up

cut_rod(p, n)
  r = {}
  r[0] = 0
  for j = 1 to n
    q = -1
    for i = 1 to j
      q = max(q, p[i] + r[j - i])
    r[j] = q
  return r[n]

La complessità sarà anche in questo caso .

Volendo si può modificare per salvare la posizione del primo taglio da fare su un'asta lunga :

cut_rod(p, n)
  r = {}
  r[0] = 0
  for j = 1 to n
    q = -1
    for i = 1 to j
      if p[i] + r[j - i] > q
        q = p[i] + r[j - i]
        s[j] = i
    r[j] = q
  return r, s

print_cut_rod(p, n)
  r, s = cut_rod(p, n)
  while n > 0
    print(s[n])
    n = n - s[n]