Come si identifica un problema come adatto alla programmazione dinamica?


19

Recentemente ho letto sulla programmazione dinamica. Mi piacerebbe avere notizie da qualcuno che ha iniziato da zero e ora è abbastanza bravo a identificare e risolvere i problemi di DP. Sto lottando per identificare questi problemi come DP e definire una soluzione concisa.

Ho attraversato la maggior parte dei problemi di DP per principianti e risorse del MIT ecc

Risposte:


17

Vengo da un background di fisica e quindi da molti calcoli matematici. Trovo i problemi facili da individuare ben adatti alle soluzioni di programmazione ricorsiva / dinamica trovando somiglianze con prove per induzione .

In prova per induzione hai due parti:

  • dimostrate che se qualcosa è vero per l'iterazione N, è vero anche per l'iterazione N + 1
  • dimostri che è vero per l'iterazione 1

Nella programmazione ricorsiva / programmazione dinamica:

  • si identifica una condizione di uscita (ad esempio, cablare la soluzione per l'iterazione 1)
  • si calcola la soluzione per l'iterazione N data la soluzione per l'iterazione N-1

Quindi, come hanno risposto gli altri, è una questione di esperienza e di raccolta dei suggerimenti, ma puoi riutilizzare altre abilità per guidarti. Dopodiché, devi sempre avere le due parti che ho citato: in caso contrario, non funzionerà.

Ad esempio, per generare tutte le permutazioni di un set:

  • condizione di uscita: se si dispone di un solo elemento, restituirlo
  • ricorsione: le permutazioni di un insieme di N elementi sono gli insiemi N di permutazioni che si ottengono scegliendo ciascun elemento e combinando tutti gli insiemi N-1 di (molte) permutazioni del sottoinsieme che si ottiene rimuovendo l'elemento.

8

La maggior parte dei problemi di programmazione dinamica può essere risolta tramite memoization. La memorizzazione è normalmente più intuitiva e più facile da codificare. Potresti trovare utile pensare in termini di memoization anziché DP.

Di solito è più facile capire se un problema è adatto alla memoizzazione (i passaggi sono gli stessi della risposta di Slivvz , ma penso che il cambiamento mentale sia un po 'più breve). Tuttavia, una volta risolto un problema tramite la memoizzazione, puoi esaminare come viene riempita la cache dei memo e quindi riempirla in ordine, senza ricorsione ... che trasforma l'algoritmo in un algoritmo di programmazione dinamica.

TL; DR; versione: potrebbe essere più semplice comprendere la programmazione dinamica in termini di memoizzazione.

Vedi anche StackOverflow: programmazione dinamica e memoization: approcci bottom-up vs top-down .


4

La programmazione dinamica riguarda in definitiva due cose:

  1. Sottostruttura ottimale
    Le soluzioni più grandi possono essere derivate da soluzioni più piccole; la soluzione non è bidirezionale.

  2. Sottoproblemi sovrapposti
    Le piccole soluzioni verranno riutilizzate più volte. Se i sottoproblemi non si sovrappongono affatto, allora non beneficiate di DP / memoisation; quello che hai è invece dividere e conquistare .

L'approccio generale ai problemi della DP è:

  • Scrivi una versione ricorsiva o iterativa ingenua che funzioni.

  • Si noti che la funzione sta eseguendo un lavoro ridondante.

  • Trova un modo per evitare di fare quel lavoro ridondante, spesso per memoria.


Tutti questi sono veri da un punto di vista teorico. L'IMO richiede un po 'più di pratica per avere più familiarità con una rapida identificazione :)
user110036

2

Non avevo mai implementato un singolo risolutore di programmazione dinamica - il mio background è la matematica applicata / fisica / informatica numerica, non CS - fino a qualche anno fa quando ho iniziato a fare problemi con Project Euler . I problemi risolvibili DP lì (ad esempio 76 , 158 , 161 , 242, ma ce ne sono molti altri) che si sono rivelati praticamente il mio genere preferito. Sicuramente migliorerai a individuare quando sarà una tecnica utile: fondamentalmente cerca cose che sembrano essere risolte da una sorta di approccio ricorsivo, divide e conquista dove è anche possibile domare l'esplosione di percorsi che richiedono da esplorare riconoscendo i sottoproblemi ricorrenti e riutilizzando i risultati precedentemente calcolati; essere in grado di identificare il vettore di stato minimo su cui memorizzare - e quale "storia" irrilevante può essere cancellata - è il passo cruciale.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.