Perbedaan Kasus pada Pemrograman Dinamis: Dibutuhkan Contoh!

19

Saya telah mengerjakan pemrograman dinamis selama beberapa waktu. Cara kanonik untuk mengevaluasi rekursi pemrograman dinamis adalah dengan membuat tabel dari semua nilai yang diperlukan dan mengisinya baris demi baris. Lihat misalnya Cormen, Leiserson et al: "Pengantar Algoritma" untuk pengantar.

Saya fokus pada skema perhitungan berbasis tabel dalam dua dimensi (pengisian baris-demi-baris) dan menyelidiki struktur dependensi sel, yaitu sel mana yang perlu dilakukan sebelum yang lain dapat dihitung. Kami menyatakan dengan set indeks sel yang bergantung pada sel . Perhatikan bahwa harus bebas siklus.Γ(i)iΓ

Saya abstrak dari fungsi aktual yang dihitung dan berkonsentrasi pada struktur rekursifnya. Secara formal, saya mempertimbangkan recurrrence menjadi pemrograman dinamis jika memiliki bentukd

d(i)=f(i,Γ~d(i))

dengan , dan beberapa fungsi (yang dapat dihitung) yang tidak menggunakan selain melalui .i[0m]×[0n]Γ~d(i)={(j,d(j))jΓd(i)}fdΓ~d

Ketika membatasi granularity dari ke area kasar (ke kiri, atas-kiri, atas, atas-kanan, ... dari sel saat ini) satu mengamati bahwa pada dasarnya ada tiga kasus (hingga simetri dan rotasi) yang valid rekursi pemrograman dinamis yang menginformasikan bagaimana tabel dapat diisi:Γd

Tiga kasus dependensi sel pemrograman dinamis

Area merah menunjukkan (perkiraan berlebihan) . Kasus satu dan dua mengakui himpunan bagian, kasus ketiga adalah kasus terburuk (hingga transformasi indeks). Perhatikan bahwa tidak sepenuhnya diwajibkan bahwa seluruh area merah dilindungi oleh ; beberapa sel di setiap bagian merah tabel cukup untuk mengecatnya merah. Area putih secara eksplisit diperlukan untuk tidak mengandung sel yang diperlukan.ΓΓ

Contoh untuk kasus satu adalah edit jarak dan urutan umum terpanjang , kasus kedua berlaku untuk Bellman & Ford dan CYK . Contoh yang kurang jelas termasuk yang bekerja pada diagonal daripada baris (atau kolom) karena dapat diputar agar sesuai dengan kasus yang diusulkan; lihat jawaban Joe sebagai contoh.

Saya tidak punya contoh (alami) untuk kasus tiga! Jadi pertanyaan saya adalah: Apa contoh untuk kasus rekursi / masalah pemrograman dinamis?

Raphael
sumber
2
Kasus 3 merangkum kasus 1 dan 2.
JeffE
Tidak, tidak, meskipun terlihat. Misalnya, kasus 1 contoh tidak dapat memiliki sel yang diperlukan di daerah kiri atas, sedangkan kasus 3 contoh harus memiliki sel yang diperlukan di daerah kiri atas. Saya mengedit penjelasan untuk mengklarifikasi.
Raphael

Jawaban:

15

Ada banyak contoh lain dari algoritma pemrograman dinamis yang tidak sesuai dengan pola Anda sama sekali.

  • Masalah kenaikan urutan terpanjang hanya membutuhkan tabel satu dimensi.

  • Ada beberapa algoritma pemrograman dinamis alami yang tabelnya membutuhkan tiga atau lebih dimensi. Sebagai contoh: Temukan persegi panjang putih area-maksimum dalam bitmap. Algoritma pemrograman dinamis alami menggunakan tabel tiga dimensi.

  • Tetapi yang paling penting, pemrograman dinamis bukan tentang tabel ; ini tentang penguraian rekursi. Ada banyak algoritma pemrograman dinamis alami di mana struktur data yang digunakan untuk menyimpan hasil antara bukan array, karena perulangan yang dibatalkan tidak melebihi rentang bilangan bulat. Dua contoh mudah adalah menemukan kumpulan simpul independen terbesar di pohon, dan menemukan subtree umum terbesar dari dua pohon. Contoh yang lebih kompleks adalah algoritma -aproximation untuk masalah salesman keliling Euclidean oleh Arora dan Mitchell.(1+ϵ)

JeffE
sumber
Terima kasih atas jawaban Anda, tetapi saya secara eksplisit membatasi pertanyaan untuk masalah dua dimensi dan skema perhitungan berbasis kanonik (diedit untuk membuat titik itu lebih jelas). Saya menyadari kerangka kerja yang lebih umum tetapi tidak tertarik pada saat ini.
Raphael
9
Oke, tapi saya pikir Anda kehilangan intinya.
JeffE
Karena ada banyak upvotes, saya pikir saya harus menjelaskan ini: Posting ini tidak menjawab pertanyaan dan bahkan tidak berusaha.
Raphael
2
@ Raphael benar. "Jawaban" saya bukanlah jawaban melainkan kritik atas pertanyaan itu, tetapi terlalu panjang untuk dikomentari.
JeffE
3

Fungsi Computing Ackermann ada dalam semangat ini. Untuk menghitung Anda perlu tahu A ( m , n - 1 ) dan A ( m - 1 , k ) untuk beberapa k besar . Koordinat kedua menurun, atau menurun pertama, dan yang kedua berpotensi meningkat.A(m,n)A(m,n1)A(m1,k)k

Ini idealnya tidak sesuai dengan persyaratan, karena jumlah kolom tidak terbatas, dan perhitungan biasanya dilakukan top-down dengan menghafal, tetapi saya pikir itu layak untuk disebutkan.

sdcvvc
sumber
1
Tidak, sarang seperti dalam tidak benar-benar cocok untuk pemrograman dinamis. Hehe, ini sangat aneh saya harus memeriksa bahwa definisi saya mengecualikan kasus tersebut entah bagaimana. DP non-primitif-rekursif, oh my ...A(m1,A(m,n1))
Raphael
1
Tidak yakin mengapa jawaban ini dibatalkan, karena itu adalah jawaban yang bagus. Fungsi Ackermann cocok untuk pemrograman dinamis. Secara umum, setiap fungsi yang didefinisikan secara rekursif yang berulang kali dihitung untuk argumen yang sama cocok untuk pemrograman dinamis. Untuk melihat ini, hanya perlu mengimplementasikannya dan membandingkan waktu berjalan. Yang membutuhkan waktu bertahun-tahun untuk menghitung dengan fungsi Ackermann biasa dapat membutuhkan waktu beberapa detik dengan fungsi pemrograman dinamis.
Jules
@ Jules: Masalah untuk skema tabel kanonik adalah bahwa Anda tidak tahu (primitif rekursif) terikat pada ukuran tabel a priori. Tentu saja Anda dapat melakukan memoisasi, tetapi tidak dengan cara yang biasa. Jadi ya, mungkin layak untuk DP tetapi tidak sesuai dengan kelas masalah yang menjadi pertanyaan saya.
Raphael
1
Saya tidak berpikir itu adalah persyaratan untuk DP bahwa Anda memiliki a priori terikat pada ukuran tabel? Bahkan seperti yang disebutkan JeffE, cache tidak harus berupa tabel sama sekali. Ini bisa berupa struktur data asosiatif. DP sebenarnya adalah ide yang sangat sederhana: Anda ingin menghitung fungsi yang didefinisikan secara rekursif, tetapi fungsi ini berulang kali dipanggil pada argumen yang sama. DP adalah optimisasi tempat Anda memperkenalkan cache untuk memastikan Anda menghitung setiap kasus hanya sekali. Ada banyak fungsi yang tidak cocok dengan kasus Anda, bahkan jika mereka adalah fungsi dari dua bilangan bulat terbatas.
Jules
2

Ini tidak cocok dengan case 3 persis, tapi saya tidak tahu apakah ada kasus Anda menangkap masalah yang sangat umum digunakan untuk mengajarkan pemrograman dinamis: Matrix Chain Multiplication . Untuk mengatasi masalah ini, (dan banyak lainnya, ini hanya yang kanonik) kami mengisi matriks diagonal dengan diagonal, bukan baris demi baris.

Jadi aturannya kira-kira seperti ini:

diagMatrix

Joe
sumber
1
Ditulis seperti ini memang tidak cocok dengan kasus apa pun. Namun, jika Anda memutar searah jarum jam sebesar 45 derajat, Anda mendapatkan case 2 (dan semua properti tersirat). Ini berlaku untuk contoh lain yang bekerja dari diagonal ke sudut juga. Tapi terima kasih sudah menyebutkannya!
Raphael
@ Raphael tidak segera jelas bahwa ini setara, Anda mungkin ingin menyebutkan itu dalam pertanyaan Anda.
Joe
0

Saya tahu ini contoh konyol, tapi saya pikir masalah iteratif yang sederhana seperti

Temukan jumlah angka dalam matriks persegi

mungkin memenuhi syarat. The "tradisional untuk setiap baris untuk setiap kolom" agak seperti kasus Anda 3.

hugomg
sumber
-1

Ini sebenarnya bukan ruang pencarian yang Anda cari, tetapi saya memiliki ide tentang bagian atas kepala saya yang mungkin bisa membantu.

Masalah:

n×nMxM

Menjawab

Ini dapat diselesaikan dengan cara rekursif berikut:

k=1+n2xmk,kx<mk,kmi,jkinkjn1/4x>mk,k1/434n2x(34)3n2

0x0
sumber
1
Ini bukan contoh pemrograman dinamis, bukan?
Raphael