Anda di halaman 1dari 6

Pemrograman Dinamis

Pemrograman dinamis, seperti metode membagi-dan-menaklukkan, memecahkan masalah


dengan menggabungkan solusi untuk subproblems. Algoritma pemrograman dinamis memecahkan
setiap subsubproblem hanya satu kali dan kemudian menyimpan jawabannya dalam sebuah tabel,
sehingga menghindari pekerjaan menghitung ulang jawabannya setiap kali menyelesaikan setiap
masalah subsubproblem.

Kami biasanya menerapkan pemrograman dinamis untuk masalah optimasi. Setiap solusi
memiliki nilai, dan kami ingin menemukan solusi dengan nilai optimal (minimum atau maksimum).
Kami menyebut solusi tersebut sebagai solusi optimal untuk masalah, berlawanan dengan solusi
optimal, karena mungkin ada beberapa solusi yang mencapai nilai optimal.

Saat mengembangkan algoritma pemrograman dinamis, kita mengikuti urutan empat langkah:
1. Mencirikan struktur solusi yang optimal.
2. Secara rekursif definisikan nilai solusi yang optimal.
3. Hitung nilai solusi optimal, biasanya dengan cara bottom-up.
4. Buat solusi optimal dari informasi yang dihitung.
Langkah 1-3 membentuk dasar solusi pemrograman dinamis untuk sebuah masalah. Jika kita
hanya membutuhkan nilai solusi optimal, dan bukan solusinya sendiri, maka kita bisa menghilangkan
langkah 4. Ketika kita melakukan langkah 4, terkadang kita menjaga informasi tambahan selama
langkah 3 sehingga kita dapat dengan mudah membuat solusi optimal.

15.1 Batang memotong


Contoh pertama kami menggunakan pemrograman dinamis untuk memecahkan masalah
sederhana dalam menentukan di mana memotong batang baja. Perhatikan bahwa untuk
memecahkan masalah asli ukuran n, kita menyelesaikan masalah yang lebih kecil dengan tipe yang
sama, namun ukurannya lebih kecil. Kami mengatakan bahwa masalah pemotongan batang
menunjukkan substruktur yang optimal: solusi optimal untuk suatu masalah memasukkan solusi
optimal untuk subproblems terkait, yang dapat kami selesaikan secara independen. Solusi optimal
mewujudkan solusi hanya pada satu subproblem yang terkait - sisanya - bukan dua.

-Menggunakan pemrograman dinamis untuk pemotongan batang optimal


Setelah mengamati bahwa solusi rekursif naif tidak efisien karena memecahkan masalah yang
sama berulang kali, kami mengatur setiap subproblem yang harus dipecahkan hanya sekali,
menghemat solusinya. Jika kita perlu mengacu pada solusi subproblem ini lagi nanti, kita bisa
mencarinya, daripada menghitungnya kembali. Pemrograman dinamis dengan demikian
menggunakan memori tambahan untuk menghemat waktu komputasi; Ini menyajikan contoh trade-
off memori waktu. Tabungan bisa jadi dramatis: solusi eksponensial bisa diubah menjadi solusi waktu
polinomial. Pendekatan pemrograman dinamis berjalan dalam waktu polinomial ketika jumlah
subproblem yang berbeda terlibat adalah polinomial dalam ukuran masukan dan kita dapat
menyelesaikan setiap subproblem tersebut dalam waktu polinomial.
Biasanya ada dua cara yang setara untuk menerapkan pendekatan pemrograman dinamis. Kita
akan mengilustrasikan keduanya dengan contoh pemotong batang kita.
Pendekatan pertama adalah top-down dengan memoization. Dalam pendekatan ini, kita
menulis prosedur secara rekursif secara alami, namun dimodifikasi untuk menyimpan hasil setiap
subproblem (biasanya dalam array atau tabel hash). Prosedur sekarang pertama memeriksa untuk
melihat apakah sebelumnya telah memecahkan masalah ini. Jika demikian, ia mengembalikan nilai
yang tersimpan, menyimpan perhitungan lebih lanjut pada tingkat ini; Jika tidak, prosedur tersebut
menghitung nilainya dengan cara biasa. Kami mengatakan bahwa prosedur rekursif telah dipo; itu
"mengingat" hasil apa yang telah dihitung sebelumnya.
Pendekatan kedua adalah metode bottom-up. Pendekatan ini biasanya bergantung pada
beberapa pengertian alami tentang "ukuran" suatu subproblem, sehingga memecahkan subproblem
tertentu hanya bergantung pada pemecahan submasalah "yang lebih kecil". Kami mengurutkan
subproblems menurut ukuran dan mengatasinya dalam ukuran, terkecil terlebih dahulu. Ketika
memecahkan subproblem tertentu, kita telah menyelesaikan semua subproblem yang lebih kecil yang
solusinya tergantung pada, dan kita telah menyelamatkan solusinya. Kami menyelesaikan setiap
subproblem hanya satu kali, dan ketika pertama kali melihatnya, kami telah menyelesaikan semua
subproblem prasyaratnya.
Kedua pendekatan ini menghasilkan algoritma dengan waktu berjalan asimtotik yang sama,
kecuali dalam keadaan yang tidak biasa dimana pendekatan top-down tidak benar-benar recurse
untuk memeriksa semua kemungkinan subproblems. Pendekatan bottom-up seringkali memiliki
faktor konstan yang jauh lebih baik, karena ia memiliki overhead yang lebih sedikit untuk panggilan
prosedur.
-Subproblem grafik
Grafik subproblem untuk masalah tersebut mewujudkan informasi ini dengan tepat. Ini adalah
grafik yang diarahkan, yang berisi satu titik untuk masing-masing subproblem yang berbeda. Kita dapat
memikirkan grafik subproblem sebagai versi "direduksi" atau "runtuh" dari pohon rekursi untuk
metode rekursif top-down, di mana kita menggabungkan semua node untuk subproblem yang sama
ke satu titik dan mengarahkan semua sisi dari induk ke anak.
Ukuran grafik subproblem (G = (V, E) dapat membantu kita menentukan waktu pelaksanaan
algoritma pemrograman dinamis. Karena kita menyelesaikan setiap subproblem sekali saja, waktu
yang berjalan adalah jumlah waktu yang dibutuhkan untuk menyelesaikan setiap subproblem.
Biasanya, waktu untuk menghitung solusi ke subproblem sebanding dengan derajat (jumlah tepi
keluar) dari verteks yang sesuai pada grafik subproblem, dan jumlah subproblem sama dengan jumlah
simpul pada grafik subproblem. Dalam kasus umum ini, waktu menjalankan pemrograman dinamis
linier dalam jumlah simpul dan sisi.

-Menghancurkan solusi
Solusi pemrograman dinamis kami untuk mengatasi masalah pemotongan batang
mengembalikan nilai solusi optimal, namun solusi tersebut tidak mengembalikan solusi aktual: daftar
ukuran potongan. Kita dapat memperluas pendekatan pemrograman dinamis untuk mencatat tidak
hanya nilai optimal yang dihitung untuk setiap subproblem, namun juga pilihan yang mengarah pada
nilai optimal. Dengan informasi ini, kami dapat dengan mudah mencetak solusi optimal.

15.2 Penggandaan rantai matriks


Penggandaan matriks bersifat asosiatif, sehingga semua tanda kurung menghasilkan produk
yang sama. Produk dari matriks sepenuhnya ditandai jika itu adalah matriks tunggal atau produk dari
dua produk matriks yang diberi tanda kurung penuh, yang dikelilingi oleh tanda kurung.

-Menghitung jumlah tanda kurung


Jumlah solusi demikian eksponensial dalam n, dan metode pencarian brute force yang
melelahkan membuat strategi yang buruk saat menentukan bagaimana menimbang secara optimal
rantai matriks.

-Menapkan pemrograman dinamis

Langkah 1: Struktur dari parenthesization yang optimal


Kami menemukan substruktur yang optimal dan kemudian menggunakannya untuk
membangun solusi optimal untuk mengatasi masalah dari solusi optimal terhadap subproblems.
Langkah 2: Solusi rekursif
Kami mendefinisikan biaya solusi optimal secara rekursif dalam hal solusi optimal untuk
subproblems.

Langkah 3: Menghitung biaya optimal


Kita bisa dengan mudah menulis algoritma rekursif berdasarkan kekambuhan untuk
menghitung biaya minimum dan kita bisa menghitung biaya optimal dengan menggunakan tabular.

Langkah 4: Membangun solusi optimal


Membagi produk. Dengan demikian kita tahu bahwa perkalian matriks terakhir dalam
komputasi.

15.3 Elemen pemrograman dinamis


Kami memeriksa dua bahan utama yang harus dilakukan masalah optimasi agar pemrograman
dinamis dapat diterapkan: substruktur optimal dan subproblem yang tumpang tindih.

-Optimal substruktur
Ingatlah bahwa masalah menunjukkan substruktur optimal jika solusi optimal untuk masalah
mengandung solusi optimal untuk subproblems.

Anda akan menemukan diri Anda mengikuti pola umum dalam menemukan substruktur yang
optimal:
1. Anda menunjukkan bahwa solusi untuk masalah terdiri dari membuat pilihan, seperti memilih
potongan awal pada batang atau memilih indeks untuk membagi rantai matriks.

2. Anda mengira bahwa untuk masalah tertentu, Anda diberi pilihan yang mengarah pada solusi
optimal. Anda belum mempedulikan diri Anda dengan bagaimana menentukan pilihan ini.

3. Dengan pilihan ini, Anda menentukan submasalahnya dan bagaimana cara terbaik untuk
mencirikan ruang subproblem yang dihasilkan.

4. Anda menunjukkan bahwa solusi untuk subproblem yang digunakan dalam solusi optimal
untuk masalah itu sendiri harus optimal dengan menggunakan teknik "cut-and-paste".
Substruktur optimal bervariasi di seluruh domain masalah dengan dua cara:
1. berapa banyak subproblems solusi optimal untuk penggunaan masalah asli, dan
2. Berapa banyak pilihan yang kita miliki dalam menentukan subproblem (s) yang akan
digunakan dalam solusi optimal.
Secara informal, waktu berjalan dari algoritma pemrograman dinamis bergantung pada produk
dua faktor: jumlah subproblem keseluruhan dan berapa banyak pilihan yang kita lihat untuk setiap
subproblem.

-Seluruh masalah subproblems


Ketika sebuah algoritma rekursif meninjau ulang masalah yang sama berulang kali, kita
mengatakan bahwa masalah optimasi memiliki masalah yang tumpang tindih. Algoritma
pemrograman dinamis biasanya memanfaatkan subproblem yang tumpang tindih dengan
memecahkan setiap subproblem satu kali dan kemudian menyimpan solusinya di meja yang dapat
dilihat saat diperlukan, menggunakan waktu konstan per pencarian.

-Menghancurkan solusi optimal


Dengan menyimpan indeks matriks di mana kita membagi produk, kita dapat merekonstruksi
setiap pilihan hanya dalam satu waktu.

-Memoisasi
Idenya adalah untuk memoize algoritma rekursif yang natural, tapi tidak efisien. Algoritma
rekursif yang memoisasi mempertahankan sebuah entri dalam sebuah tabel untuk solusi terhadap
setiap subproblem. Ketika subproblem pertama kali ditemukan sebagai algoritma rekursif yang
terbentang, solusinya dihitung dan kemudian disimpan di tabel. Setiap kali kita menghadapi
subproblem ini, kita hanya melihat nilai yang tersimpan di tabel dan mengembalikannya.

15.4 Persamaan umum terpanjang


Sekumpulan DNA terdiri dari serangkaian molekul yang disebut basis, di mana basis yang
mungkin adalah adenin, guanin, sitosin, dan timin.

Langkah 1: Mencirikan urutan umum terpanjang


Kami akan menghitung semua kemunculan X dan memeriksa setiap subsequence untuk melihat
apakah itu juga merupakan kemunculan Y, mencatat keterkaitan terpanjang yang kami temukan.
Langkah 2: Solusi rekursif
Kita dapat dengan mudah melihat properti overclocking-subproblems dalam masalah LCS.
Langkah 3: Komputasi panjang LCS
Kita bisa dengan mudah menulis algoritma rekursif eksponensial-waktu untuk menghitung
panjang LCS dari dua urutan.
Langkah 4: Membangun SKB
Tabel yang dikembalikan oleh LCS-LENGTH memungkinkan kita untuk segera membuat LCS.

-Meningkatkan kode
Beberapa perubahan dapat menyederhanakan kode dan memperbaiki faktor konstan namun
sebaliknya tidak menghasilkan perbaikan kinerja asimtotik. Orang lain dapat menghasilkan
penghematan asimtotik yang substansial dalam ruang dan waktu.

15.5 Pohon pencarian biner optimal


Yang kita butuhkan dikenal sebagai pohon pencari biner yang optimal. Untuk sekumpulan
probabilitas tertentu, kami ingin membuat pohon pencarian biner yang biaya pencariannya paling
diminati. Kami menyebut pohon itu sebagai pohon pencarian biner yang optimal.
Langkah 1: Struktur pohon pencarian biner yang optimal
Kita mulai dengan pengamatan tentang subtree. Pertimbangkan subtree dari pohon pencarian
biner.
Langkah 2: Solusi rekursif
Kami memilih domain subproblem kami untuk menemukan pohon pencarian biner yang
optimal yang berisi tombolnya
Langkah 3: Menghitung biaya pencarian yang diharapkan dari pohon pencarian biner yang
optimal
Untuk kedua masalah domain, subproblems kami terdiri dari subrang indeks bersebelahan.
Indeks kedua perlu dimulai dari 0 karena untuk memiliki subtree yang hanya berisi kunci dummy, kita
perlu menghitung dan menyimpannya.

Anda mungkin juga menyukai