Salta al contenuto
Note per Studenti Esercizio 11 · massimo beneficio lungo un cammino radice-foglia

Esercizio 11massimo beneficio lungo un cammino radice-foglia

In questa pagina 5

Testo (scritto del 10/09/2026, seconda parte, esercizio 2, 6 punti). Una città sta valutando un piano pluriennale per ridurre le proprie emissioni di gas serra. Il piano prevede una sequenza di decisioni su possibili interventi; per ciascuno si deve decidere se realizzarlo oppure no. Le possibili evoluzioni del piano sono rappresentate mediante un albero binario: ogni nodo rappresenta l'esito di una scelta già effettuata e i suoi due figli rappresentano le due possibili scelte relative all'intervento successivo. A ogni nodo è associato un valore intero (il beneficio climatico netto stimato della scelta, in tonnellate di CO2_2 risparmiate), che può essere positivo o negativo. Il beneficio complessivo di un piano è la somma dei valori dei nodi lungo il cammino dalla radice a una foglia. Si vuole progettare un algoritmo ricorsivo bestClimatePlan(root) che restituisca il massimo beneficio complessivo tra tutti i piani rappresentati nell'albero.

(a) Spiegare a parole l'idea della soluzione ricorsiva, aiutandosi con un albero di esempio. (b) Scrivere lo pseudocodice di bestClimatePlan(root), specificando input e output. (c) Analizzare la complessità al caso pessimo in funzione del numero nn di nodi, in notazione O(⋅)O(\cdot), Ω(⋅)\Omega(\cdot) ed eventualmente Θ(⋅)\Theta(\cdot), giustificando.


Richiami

Visita ricorsiva in postorder: il risultato di un nodo dipende da quello dei figli (vedi Visite di alberiVisite in preorder e postorder come schemi generali (template) da adattare; complessità Theta(n + somma dei costi di visita) perché la somma dei figli è n-1; esempi (indice di un libro, spazio occupato in un file system); profondità con il preorder, altezza con il postorder; antenato comune più basso.Visite di alberi → e Algoritmi ricorsiviAlgoritmi ricorsivi come induzione eseguita; albero della ricorsione e record di attivazione nello stack; esempi ReverseArray, LinearSum, Power in tempo logaritmico, Fibonacci ricorsivo (esponenziale) e con memoizzazione; analisi della complessità con l'albero della ricorsione e correttezza per induzione.Algoritmi ricorsivi →).

(a) Idea

Il miglior piano che parte da un nodo vv prende il valore di vv e poi sceglie il sottoalbero migliore tra i due. Se vv è una foglia, c'è un solo piano e vale v.value. Quindi, indicando con B(v)B(v) il massimo beneficio dei cammini da vv a una foglia di TvT_v:

B(v)={v.valuev fogliav.value+max⁡{B(left(v)), B(right(v))}altrimenti.B(v) = \begin{cases} v.\text{value} & v \text{ foglia} \\ v.\text{value} + \max\{B(\text{left}(v)),\, B(\text{right}(v))\} & \text{altrimenti.} \end{cases}

Si noti che non basta sommare i valori positivi: il cammino deve arrivare a una foglia, anche attraversando valori negativi.

Esempio: radice 55, figli 22 e 77; 22 ha figli (foglie) 44 e 11; 77 ha figli (foglie) 33 e −2-2. I quattro piani valgono 5+2+4=115+2+4 = 11, 5+2+1=85+2+1 = 8, 5+7+3=155+7+3 = 15, 5+7+(−2)=105+7+(-2) = 10. In basso: B(2)=2+max⁡(4,1)=6B(2) = 2 + \max(4, 1) = 6, B(7)=7+max⁡(3,−2)=10B(7) = 7 + \max(3, -2) = 10; in radice B=5+max⁡(6,10)=15B = 5 + \max(6, 10) = 15 ✓.

(b) Pseudocodice

Algoritmo bestClimatePlan(v)
Input: nodo v di un albero binario non vuoto; ogni nodo ha un campo intero value
Output: massimo, tra i cammini da v a una foglia di T_v, della somma dei value
if v è una foglia then return v.value
best <- -infinito
if v ha il figlio sinistro then best <- max(best, bestClimatePlan(left(v)))
if v ha il figlio destro  then best <- max(best, bestClimatePlan(right(v)))
return v.value + best

Chiamata: bestClimatePlan(root). (Se tutti i nodi interni hanno due figli, come nel testo, i due if sono sempre veri; la versione generale gestisce anche un solo figlio.)

Correttezza (induzione sull'altezza). Foglia: l'unico cammino ha somma v.value ✓. Nodo interno: ogni cammino da vv a una foglia è vv seguito da un cammino da un figlio a una foglia; la somma è v.value più la somma del sottocammino, quindi il massimo si ottiene con il massimo sottocammino di un figlio, che per ipotesi induttiva restituiscono le chiamate ricorsive.

(c) Complessità

È una visita in postorder: l'albero della ricorsione ha esattamente un nodo per ogni nodo di TT (ogni nodo è visitato una sola volta, indipendentemente dai valori) e il costo locale di ogni chiamata, escluse le figlie, è Θ(1)\Theta(1) (confronti, un massimo, una somma). Quindi

t(n)∈O(n)et(n)∈Ω(n)  ⟹  t(n)∈Θ(n).t(n) \in O(n) \quad \text{e} \quad t(n) \in \Omega(n) \implies t(n) \in \Theta(n).

Non si può evitare di guardare tutti i nodi: un valore molto grande nascosto in una foglia qualsiasi può cambiare il risultato.

Errori comuni

  • Sommare solo i valori positivi o fermarsi quando il beneficio parziale scende: un valore negativo può essere seguito da uno molto positivo.
  • Scegliere ad ogni nodo il figlio col valore più grande (algoritmo greedy): sbagliato. Nell'esempio da 55 il figlio 7>27 > 2 è quello giusto, ma con foglie 3,−23, -2 sotto 77 e 100,100100, 100 sotto 22 la scelta golosa (77) darebbe 1515 contro 5+2+100=1075 + 2 + 100 = 107.
  • Confondere il cammino fino a una foglia con un cammino qualunque dalla radice (il testo chiede la foglia).
  • Restituire una struttura più complicata del necessario (ad esempio il cammino intero): l'output richiesto è il solo beneficio massimo.

Versione ripasso

Testo. Albero binario con valori interi (positivi o negativi) nei nodi; beneficio di un piano = somma dei valori da radice a una foglia; bestClimatePlan(root) = massimo beneficio. Idea, pseudocodice, complessità.

Teoria collegata