My first Magazine pemrograman-kompetitif-dasar | Page 81

7.2 Contoh-contoh DP Sederhana d p(1, _), d p(2, _), ..., d p(i − 2, _) tidak lagi dibutuhkan. Dengan demikian, kita dapat menghemat memori dengan tidak lagi menyimpan informasi yang sudah tidak dibutuhkan. Untuk mewujudkannya, kita dapat membuat tabel DP yang hanya berukuran 2 × G. Pada awalnya, baris ke-0 digunakan untuk menyimpan d p(0, _), dan baris ke-1 untuk d p(1, _). Untuk perhitungan d p(2, _), kita tidak lagi membutuhkan d p(0, _), sehingga baris menyimpan d p(0, _) dapat ditimpa untuk menyimpan d p(2, _). Demikian pula untuk d p(3, _), yang dapat menimpa baris yang menyimpan d p(1, _). Secara umum, d p(x, _) akan disimpan pada baris ke-(x mod 2). Optimisasi seperti ini disebut dengan flying table atau rolling array, dan ditunjukkan pada Algoritma 32. Algoritma 32 Knapsack secara bottom-up dengan optimisasi flying table . function SOLVE () d p ← new integer[2][G + 1] 3: for c ← 0, G do 4: d p[0][c] ← 0 5: end for 1: 2: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: for i ← 1, N do iNow ← i mod 2 iPrev ← 1 − iNow . Bernilai 0 atau 1 yang merupakan kebalikan dari iNow for c ← 0, G do best ← d p[iPrev][c] if (c ≥ w[i]) then best ← max(best, d p[iPrev][c − w[i]] + v[i]) end if d p[iNow][c] ← best end for end for return d p[N mod 2][G] end function Dengan optimisasi ini, kebutuhan memorinya berkurang dari O(NG) menjadi O(G). Perlu diperhatikan bahwa flying table hanya mengurangi kompleksitas memori. Kompleksitas waktu untuk perhitungan DP tetaplah sama. Lebih jauh lagi, kita dapat menghilangkan dimensi i pada DP secara sepenuhnya, sehingga cukup digunakan tabel 1 dimensi berukuran G. Perhatikan bahwa pengisian d p(i, c) hanya bergan- tung pada dua nilai, yaitu d p(i − 1, c) dan d p(i − 1, c − w[i]), atau dengan kata lain, nilai yang tepat berada "di atas" dan "di atas kiri" sel sebuah tabel DP. Observasi ini memungkinkan kita untuk mengisi suatu d p(i, c) dengan c yang menurun dari G sampai dengan w[i], dan langsung menimpa sel tabel d p(i − 1, c). Pengisian perlu dilakukan dengan c yang menurun (atau bila dilihat pada tabel DP, dari kanan ke kiri) supaya nilai yang disimpan pada kolom c − w[i] masih merupakan nilai d p(i − 1, c − w[i]), bukan d p(i, c − w[i]). Optimisasi lanjutan ini ditunjukkan pada Algoritma 33. Mengoptimisasi memori DP dari 2 × G menjadi G saja mungkin tidak signifikan. Penjelasan mengenai teknik flying table lebih lanjut ini hanya bertujuan untuk menunjukkan bahwa terdapat hal-hal menarik yang dapat dilakukan ketika DP diimplementasikan secara bottom-up . 71