Ecco come funziona:
1. Struttura ricorsiva: I problemi di programmazione dinamica spesso si prestano a soluzioni ricorsive. Un'ingenua implementazione ricorsiva calcolerebbe ripetutamente le soluzioni agli stessi sottoproblemi, portando alla complessità del tempo esponenziale.
2. Schemazione dei risultati: La memorizzazione introduce una struttura di dati (di solito una tabella o array di hash) per archiviare le soluzioni ai sottoproblemi già calcolati. Questa struttura è spesso chiamata "memo" o "cache".
3. Controllando il promemoria: Prima di risolvere in modo ricorsivo un sottoproblema, l'algoritmo controlla prima il promemoria. Se la soluzione è già presente (il che significa che il sottoproblema è stato risolto in precedenza), viene recuperato direttamente dal promemoria, evitando la ricomposizione.
4. Scorri il risultato: Se la soluzione non si trova nel memo, l'algoritmo risolve in modo ricorsivo il sottoproblema, quindi * memorizza * il risultato nel memo prima di restituirlo.
Esempio:
Considera il calcolo della sequenza di Fibonacci. Un approccio ricorsivo ingenuo ha una complessità esponenziale perché ricalcola molti numeri di Fibonacci più volte. Con memoizzazione:
`` `Python
Memo ={} # Inizializza il promemoria
def fibonacci_memo (n):
Se N in memo:
restituire il promemoria [n] # recuperare dal promemoria se già calcolato
Se n <=1:
restituire n
altro:
risultato =fibonacci_memo (n-1) + fibonacci_memo (n-2)
Memo [n] =risultato # memorizzare il risultato nel memo
risultato di ritorno
print (fibonacci_memo (5)) # output:5
`` `
In questo esempio, `Memo` memorizza i numeri di Fibonacci calcolati. Quando viene chiamato `fibonacci_memo (5)`, chiama ricorsivamente `fibonacci_memo (4)` e `fibonacci_memo (3)`. `fibonacci_memo (3)` Chiamerà ricorsivamente `fibonacci_memo (2)` e `fibonacci_memo (1)`. Tuttavia, una volta `fibonacci_memo (1)` o `fibonacci_memo (2)` viene calcolato e archiviato in `memo`, le successive chiamate a questi stessi sottoproblemi restituiranno direttamente i risultati memorizzati, evitando il calcolo ridondante. Ciò riduce la complessità temporale da esponenziale a lineare.
In sostanza, la memorizzazione trasforma un algoritmo ricorsivo a tempo esponenziale potenzialmente esponenziale in un algoritmo a tempo lineare (o tempo polinomiale in altri casi) sfruttando la potenza della memorizzazione nella cache dei risultati precedentemente calcolati. È una potente tecnica di ottimizzazione spesso utilizzata insieme alla programmazione dinamica per migliorare l'efficienza.
Programmazione © www.354353.com