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 CO 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 di nodi, in notazione , ed eventualmente , 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 prende il valore di e poi sceglie il sottoalbero migliore tra i due. Se è una foglia, c'è un solo piano e vale v.value. Quindi, indicando con il massimo beneficio dei cammini da a una foglia di :
Si noti che non basta sommare i valori positivi: il cammino deve arrivare a una foglia, anche attraversando valori negativi.
Esempio: radice , figli e ; ha figli (foglie) e ; ha figli (foglie) e . I quattro piani valgono , , , . In basso: , ; in radice ✓.
(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 + bestChiamata: 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 a una foglia è 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 (ogni nodo è visitato una sola volta, indipendentemente dai valori) e il costo locale di ogni chiamata, escluse le figlie, è (confronti, un massimo, una somma). Quindi
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 il figlio è quello giusto, ma con foglie sotto e sotto la scelta golosa () darebbe contro .
- 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à.
- Idea: se foglia, altrimenti ; il cammino deve arrivare a una foglia (vedi 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 →).
- Esempio: radice ; figli (foglie ) e (foglie ): piani ⇒ .
- Pseudocodice: foglia ⇒
value; altrimentibest= massimo tra le chiamate sui figli esistenti; restituiscevalue + best. - Complessità: una chiamata per nodo, costo costante, nessuna potatura possibile: (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 →).
- Correttezza (induzione sull'altezza): ogni cammino da a una foglia è più un cammino da un figlio, quindi il massimo usa il massimo dei figli. Greedy sbagliato: radice , figli (foglie ) e (foglie ): da si ha , da si ha .
- Errori: sommare solo i positivi; scelta golosa del figlio col valore maggiore; cammino non fino a una foglia.