Dinamik programlama, algoritma tasarımı hakkında düşünmenin bir yolunu sunar. Bu genellikle çok yardımcı olur.
Notlandırma ve aşağıdan yukarıya alma yöntemleri, tekrarlama ilişkilerini koda dönüştürmek için size bir kural / yöntem sunar. Notlandırma, nispeten basit bir fikirdir, ancak en iyi fikirler genellikle!
Dinamik programlama, algoritmanızın çalışma zamanını düşünmek için size yapısal bir yol sunar. Çalışma süresi temel olarak iki sayı ile belirlenir: çözmeniz gereken alt problem sayısı ve her bir alt problemin çözülmesi için geçen süre. Bu, algoritma tasarım problemi hakkında düşünmenin kolay ve kolay bir yolunu sağlar. Bir aday yineleme ilişkiniz olduğunda, ona bakabilir ve çalışma süresinin ne olabileceğini çok hızlı bir şekilde anlayabilirsiniz (örneğin, genellikle kaç tane alt problemin olacağına dair çok hızlı bir şekilde söyleyebilirsiniz). çalışma zamanı; katlanarak çözmeniz gereken birçok alt sorun varsa, tekrarlama muhtemelen iyi bir yaklaşım olmayacaktır). Bu ayrıca aday alt problem ayrıştırmalarını ekarte etmenize yardımcı olur. Örneğin, bir , S [ 1 .. i ] önekiyle veya S [ j . . n ] veya alt dizgi S [ i . . j ] makul olabilir (alt problemlerin sayısı n'de polinomdur), ancak bir alt problemin S'nin bir sonucu ile tanımlanmasının iyi bir yaklaşım olması muhtemel değildir (alt problemlerin sayısı n'de üsteldir). Bu, olası yinelemelerin "arama alanını" ayarlamanızı sağlar.S[1..n]S[1..i]S[j..n]S[i..j]nSn
Dinamik programlama, aday yinelenme ilişkilerini aramak için size yapısal bir yaklaşım sunar. Ampirik olarak, bu yaklaşım genellikle etkilidir. Özellikle, girişin türüne bağlı olarak alt sorunları tanımlamanın ortak yollarını tanıyabileceğiniz bazı sezgisel / ortak modeller vardır. Örneğin:
Girişi ise pozitif bir tam sayı , bir subproblem tanımlamak için bir aday yol değiştirerek olup , n daha küçük bir tamsayı , n ' (st 0 ≤ n ' ≤ n ).nnn′0≤n′≤n
Girişi ise dize , bir subproblem tanımlamak için bir aday yollar içerir: yerini S [ 1 .. n ] bir önek ile S [ 1 .. i ] ; yerine S [ 1 .. n ] bir sonek ile S [ j . . n ] ; yerine S [ 1 .. n ] bir alt ile S [ i . . j ]S[1..n]S[1..n]S[1..i]S[1..n]S[j..n]S[1..n]S[i..j]. (Burada alt problem, seçimi ile belirlenir .)i,j
Girdi bir liste ise , bir dize için yaptığınız gibi yapın.
Girişi ise ağaç , bir subproblem tanımlamak için bir aday yol değiştirmektir T herhangi alt ağaç ile T (yani, bir düğüm çekme x ve yerine T kökü alt ağaç ile x , subproblem seçimiyle belirlenir x ).TTTxTxx
Giriş bir çift , her biri için bir alt problemi seçmenin bir yolunu tanımlamak için , x tipine ve y tipine tekrarlı olarak bakın. Diğer bir deyişle, bir subproblem tanımlamak için bir aday yol değiştirmektir ( x , y ) ile ( x ' , y ' ) x ' bir subproblem olan x ve y ' için subproblem olan y . (Ayrıca formun alt problemlerini de düşünebilirsiniz ( x , y(x,y)xy(x,y)(x′,y′)x′xy′y Veya ( x ′ , y ) .)(x,y′)(x′,y)
Ve bunun gibi. Bu size çok faydalı bir sezgisel bakış sunar: sadece yöntemin türüne ait imzayı inceleyerek , alt sorunları tanımlamak için aday yolların bir listesini bulabilirsiniz. Başka bir deyişle, yalnızca sorun ifadesine bakarak - yalnızca girdi türlerine bakarak - bir alt sorunu tanımlamak için bir kaç aday yöntemle karşılaşabilirsiniz.
Bu genellikle çok faydalıdır. Tekrarlama ilişkisinin ne olduğunu söylemez, ancak alt problemin nasıl tanımlanacağı konusunda özel bir seçeneğiniz olduğunda, çoğu zaman karşılık gelen bir tekrarlama ilişkisini çözmek çok zor değildir. Bu nedenle, genellikle dinamik bir programlama algoritmasının tasarımını yapılandırılmış bir deneyime dönüştürür. Hurda kağıda alt sorunları tanımlamak için aday yöntemlerin bir listesini yazarsınız (yukarıdaki sezgisel yöntemi kullanarak). Daha sonra, her aday için, bir tekrarlama ilişkisi yazmayı denersiniz ve çalışma süresini alt problem sayısını ve alt problem başına harcanan zamanı sayarak değerlendirirsiniz. Her adayı denedikten sonra bulabildiğiniz en iyisini elde edersiniz. Algoritma tasarım sürecine bir yapı sağlamak, aksi takdirde algoritma tasarımını korkutucu olabileceğinden, büyük bir yardımdır.