Programowanie dynamiczne pozwala myśleć o projektowaniu algorytmów. Jest to często bardzo pomocne.
Metody zapamiętywania i oddolne dają regułę / metodę przekształcania relacji powtarzalności w kod. Zapamiętywanie jest stosunkowo prostym pomysłem, ale często są to najlepsze pomysły!
Programowanie dynamiczne daje uporządkowany sposób myślenia o czasie działania algorytmu. Czas działania zależy zasadniczo od dwóch liczb: liczby podproblemów, które należy rozwiązać, oraz czasu potrzebnego na rozwiązanie każdego podproblemu. Zapewnia to wygodny i łatwy sposób myślenia o problemie z algorytmem. Gdy masz relację powtarzalności kandydata, możesz na nią spojrzeć i bardzo szybko zorientować się, jaki może być czas działania (na przykład często możesz bardzo szybko powiedzieć, ile będzie podproblemów, co jest dolną granicą czas działania; jeśli istnieje wykładniczo wiele podproblemów, które musisz rozwiązać, to prawdopodobnie nie będzie to dobre podejście). Pomaga to również wykluczyć rozkład kandydatów na podproblemy. Na przykład, jeśli mamy ciągS [ 1 .. i ] S [ j . . n ] S [ i . . j ] n S nS[1..n], Wyznaczając subproblem prefiksem lub przyrostek lub podciągu może być rozsądne (liczba podproblemów jest wielomian ), ale obejmującym subproblem przez podciąg nie może być podejście dobry (liczba podproblemów wykładniczo w ). Pozwala to przycinać „przestrzeń wyszukiwania” możliwych powtórzeń.S[1..i]S[j..n]S[i..j]nSn
Programowanie dynamiczne zapewnia ustrukturyzowane podejście do wyszukiwania relacji powtarzalności kandydatów. Pod względem empirycznym takie podejście jest często skuteczne. W szczególności istnieją pewne heurystyki / wspólne wzorce, które można rozpoznać dla typowych sposobów definiowania podproblemów, w zależności od rodzaju danych wejściowych. Na przykład:
Jeśli wejście jest dodatnią liczbą całkowitą , jednym z kandydujących sposobów zdefiniowania podproblemu jest zastąpienie mniejszą liczbą całkowitą (st ).n n ′ 0 ≤ n ′ ≤ nnnn′0≤n′≤n
Jeśli dane wejściowe są ciągiem , niektóre potencjalne sposoby zdefiniowania podproblemu obejmują: zamień na prefiks ; zastąp sufiksem ; zamień na podciąg . (Tutaj podproblem zależy od wyboru .)S [ 1 .. n ] S [ 1 .. i ] S [ 1 .. n ] S [ j . . n ] S [ 1 .. n ] S [ i . . j ] i , jS[1..n]S[1..n]S[1..i]S[1..n]S[j..n]S[1..n]S[i..j]i,j
Jeśli dane wejściowe to lista , zrób to samo, co dla łańcucha.
Jeśli dane wejściowe to drzewo , jednym z kandydujących sposobów zdefiniowania podproblemu jest zastąpienie dowolnym poddrzewem (tj. Wybranie węzła i zastąpienie poddrzewem zrootowanym na ; podproblem zależy od wyboru ).T T x T x xTTTxTxx
Jeśli dane wejściowe to para , następnie rekurencyjnie spójrz na typ i typ aby zidentyfikować sposób wyboru podproblemu dla każdego. Innymi słowy, jednym z kandydujących sposobów zdefiniowania podproblemu jest zastąpienie przez gdzie jest podproblemem dla a jest podproblemem dla . (Można również rozważyć podproblemy postaci lub .)x y ( x , y ) ( x ′ , y ′ ) x ′ x y ′ y ( x , y ′ ) ( x ′ , y )(x,y)xy(x,y)(x′,y′)x′xy′y(x,y′)(x′,y)
I tak dalej. Daje to bardzo przydatną heurystykę: po prostu patrząc na podpis typu metody, możesz wymyślić listę potencjalnych sposobów definiowania podproblemów. Innymi słowy, po prostu patrząc na opis problemu - patrząc tylko na rodzaje danych wejściowych - możesz wymyślić kilka kandydujących sposobów zdefiniowania podproblemu.
Jest to często bardzo pomocne. Nie mówi ci, jaka jest relacja powtarzalności, ale kiedy masz konkretny wybór, jak zdefiniować podproblem, często nie jest trudno wypracować odpowiednią relację powtarzalności. Często zmienia więc dynamiczny algorytm programowania w ustrukturyzowane środowisko. Na kartce papieru zapisujesz listę potencjalnych sposobów definiowania podproblemów (korzystając z powyższej heurystyki). Następnie dla każdego kandydata próbujesz zapisać relację powtarzalności i ocenić jego czas działania, licząc liczbę podproblemów i czas spędzony na podproblem. Po wypróbowaniu każdego kandydata zachowujesz najlepszego, jaki udało ci się znaleźć. Zapewnienie pewnej struktury w procesie projektowania algorytmu jest dużą pomocą, ponieważ w przeciwnym razie projektowanie algorytmu może być zastraszające (tam „