By : Stacia E. J
DP: Top Down vs Bottom Up (kelebihan)
Top Down
✚Hanya mengerjakan state yang diperlukan
✚Mudah diimplementasi untuk state yang banyak
Bottom Up
✚Tidak ada overhead pemanggilan fungsi
✚Bisa dibuat lebih efisien dengan bantuan struktur data eksternal
✚Bisa flying table
DP: Top Down vs Bottom Up (kekurangan)
Top Down
- Ada overhead pemanggilan fungsi
- Cenderung sulit diimplementasikan struktur data eksternal untuk
efisiensi
Bottom Up
- Mengisi seluruh tabel
- Jika dimensi state besar lebih sulit untuk mengisi tabel
Contoh Soal 1 Backtrack Solusi :
• Diberikan koin dengan nominal koin[i] dalam jumlah
tak terhingga
• Banyak jenis koin M
• Cari banyak koin minimal untuk menukarkan uang
sebesar X!
• Cetak juga konfigurasi koinnya
Iterasi semua kemungkinan X, lalu dalamnya iterasi semua
kemungkinan value koin.
for(int i=1;i<=X;i++)
dp[i] = INF;
for(int j=0;j<M;j++)
if(i – koin[j] >=0 && dp[i-koin[j]] + 1 < dp[i])
dp[i] = dp[i – koin[j]] + 1;
Cara backtrack?
Iterasi semua kemungkinan X, lalu dalamnya iterasi semua
kemungkinan value koin.
for(int i=1;i<=X;i++)
dp[i] = INF;
for(int j=0;j<M;j++)
if(i – koin[j] >=0 && dp[i-koin[j]] + 1 < dp[i])
dp[i] = dp[i – koin[j]] + 1; prev[i]=j;
• 1 ≤ N ≤ 1.000
• 1 ≤ N ≤ 105
1 ≤ N ≤ 1.000
• DP[i] = panjang LIS yang berakhir di elemen dengan index i
• Waktu hitung DP[i], lihat untuk semua index j < i, cek apa
DP[j] + 1 > DP[i] dan value[j] < value[i]
• Kalau ya -> update DP[i] = DP[j] + 1
• Hasil LIS = max dari DP[0..N-1]
• O(N2)
• Cara cetak solusi?
• Tambahkan 1 array prev[i] buat catat index angka”
yang kepilih
• Pertama set semua prev[i] = -1
• Waktu iterasi DP, kalau if yang tadi True -> ganti juga
prev[i] = j
• Terus waktu cari jawaban hasil DP maksimum di akhir,
catat juga index yang kepilih jadi awal buat rekursi
• Loop dari index akhir itu, selama prev[current] != -1,
loop terus sambil print hasilnya
1 ≤ N ≤ 105 ?
S[pos] = bilangan bulat terkecil yang mengakhiri increasing sequence
dengan panjang pos.
Iterasi untuk semua bilangan bulat X di input, lakukan salah satu dari:
• Jika X > elemen terakhir di S, tambahkan X ke ujung akhir S LIS
baru
• Temukan elemen terkecil di S yang ≥ X, ganti jadi X bisa pakai
binary search karena elemen di S pasti sorted setiap saat
Kompleksitas = O(N log N)
Cara cetak hasil?
Buat array lain, Mis. Parent[i] = predecessor elemen dengan
index i di LIS yang berakhir di elemen dengan index I
Supaya mudah, yang disimpan di array S bukan bilangan
bulat yang dipilih, tapi indexnya dalam input
Waktu iterasi bilangan X
• Jika X > elemen terakhir di S, maka parent[index X] = index
dari elemen terakhir parent dari element terbaru
adalah elemen terakhir itu
• Selain itu, cari index dengan nilai elemen terkecil yang ≥ X,
dan ganti itu menjadi X. parent[index X] = S[index – 1]
Berarti LIS-nya di
input [ S [lastElementofS] ]
input [ parent [ S [lastElementofS] ] ]
input [ parent [ parent [ S [lastElemtnofS] ] ] ]
Dst.
Cara Optimasi DP
• Flying Table
• DP Map
• Dll.
Flying Table
• Jika ada fungsi dp(x, ..) yang rekurensnya hanya
melibatkan dp(x-1, …), maka nilai dp(x-2, ...),
dp(x-3, ..), dst tidak diperlukan bisa dibuang
• Jadi tabel DP hanya dibutuhkan 2 ruang, dp(now,
...) dan dp(prev, ...)
Contoh Soal :
• Ada trek (anggap seperti array 1 dimensi) sepanjang N
• Di beberapa tempat di trek itu ada tembok yang tidak bisa dilewati
• Ada orang mau jalan dari posisi 0 ke N-1
• Waktu untuk jalan di trek dari posisi i ke i+1 adalah 1 unit
• Dikasih K peluru
• Kalau ada tembok :
• Boleh tembak tembok peluru berkurang terus lewat
• Jalan di luar trek itu. Waktu untuk jalan dari trek[i] ke off-trek[i],
off-trek[i] ke off ke trek[i+1], dan off-trek[i] ke trek[i] = 2 unit
• Minimal waktu? 2 ≤ N ≤ 10.000, 0 ≤ K ≤ 10.000
Original Problem: SPOJ POWERCAR – Car with Powers
DP[track/offtrack][N][K] = minimum waktu
f(track, i, j) = min 1 + f(1, i+1, j-(kalau tembok=1)) //tetap jalan di track
4 + f(0, i+1, j) //pindah ke offtrack,jalan ke kanan offtrack
3 + f(0, i+1, j-(kalau tembok=1)) //jalan ke kanan 1, lalu ke offtrack
f(offtrack, i, j) = min 4 + f(1, i+1, j) //jalan ke kanan off track, balik ke track
3 + f(1, i+1, j-(kalau tembok=1)) //balik ke track, jalan ke kanan track
2 + f(0, i+1, j) //jalan ke kanan offtrack
Kompleksitas : O(N4) AC
Contoh Soal : Barisan Panda (BNPC 2008)
• Ada N panda, dinomori 1 sampai N (ga urut)
• Panda-panda berbaris ke belakang
• Panda dengan nomor x bisa melihat panda dengan nomor y,
jika y berada di belakang x dan x>y
• Tentukan banyak barisan yang memiliki tepat K pasang panda
yang salah satu bisa melihat panda lainnya!
• N ≤ 200
• K ≤ N*(N-1)/2
• Setiap kali mengambil bilangan terkecil ke-x, jumlah
inversi yg bertambah = x-1, sisa inversi yg harus
dibentuk k-(x-1)
• F(n, k) = banyak permutasi n bilangan yang memiliki
tepat k inversi.
• F(n, 0) = 1
• F(n, k) = F(n-1, k) + F(n-1, k-1) + F(n-1, k-2) + … + F(n-1,
k-(n-1))
• Kompleksitas: O(n2 k) --> TLE
• Untuk optimasi, lihat cara pengisian tabel
8 5
3
Memenuhi kondisi 2 berarti
1 answer += ceil((16 – 11)/2)
answer += 3
2 7
11
38 5
3
Jumlah branch = 20
1 Branch maksimum = 11
Sisa rute = 2
2 7 Branch dari node skrg ke parent = 1
11 Memenuhi kondisi 1
8 5
3
Answer += 11 – 1
1 Answer += 10
2 7
11
8 5
3
Answer += 11 – 1
1 Answer += 10
2 7
11
10
8 5
3
Jumlah branch = 1
1 Maksimum branch = 1
Sisa branch = 1
2 7 Branch dari node ke parent = 0
11 Memenuhi kondisi 1
Answer += 1 – 0
Answer += 1
8 5
3
Matroid
Ada set E = { e1, e2, ..., en } yang berisi n objek, dan masing”
punya weight yang berupa bilangan non-negatif w(e1),
w(e2), ..., w(en)
Mis. I adalah subset dari powerset E dengan properti:
1. Untuk semua I1 dalam I, jika I2 adalah subset dari I1, maka I2
pasti di dalam I
2. Untuk setiap pasangan I1 dan I2 dalam I sehingga |I2| = |I1|
+ 1, maka pasti ada elemen e dalam I2-I1 yang bisa
menyebabkan I1 U {e} berada dalam I
• Matroid -> pasangan (E, I)
• Jadi I = set hasil (belum tentu optimal, tapi pasti valid)
• Anggota dari I itu disebut independent set
• Maximum cardinality independent set = independent
set yang mengandung elemen paling banyak
• Problem untuk mencari maximum cardinality
independent set (Imax) yang meminimalkan
(/memaksimalkan) jumlah weight dari elemen Imax bisa
diselesaikan secara greedy
Algoritma Greedy
Set T = {}
Urutkan semua objek dalam E sesuai weightnya
(increasing/decreasing)
Ulang sampai E kosong
x = elemen E yg lagi diproses
hapus x dari E
Jika T U {e} di dalam I masukkan e ke T
Contoh Soal: Minimum Spanning Tree
I2 e I1 I1 U {e}
• Ada edge e dalam I2 yang punya 1 vertex sama dengan satu
vertex pada 1 connected component pada I1 dan vertex
lainnya sama dengan satu vertex pada connected component
lain pada I1, karena dua connected component adalah tree,
maka I1 U {e} adalah forest
I2 e I1 I1 U {e}
• Untuk setiap edge [v, w] di dalam I2, v dan w
berada dalam connected component I1 yang
sama Case ini tidak mungkin, karena berarti
ada minimal 1 connected component dari I1 yang
mengandung banyak edge dari I2 lebih banyak
dari banyak edge dalam I1 di komponen tsb
kontradiksi berarti terbukti kalau bisa dipilih e
dari I2-I1 sehingga I1 U {e} berada di dalam I
Contoh Soal: Job Sequencing Problem
• Ada mesin yang mau proses N kerjaan.
• Semua kerjaan membutuhkan waktu pemrosesan yang sama.
• Setiap kerjaan j punya deadline dj, dan penalti pj, yang harus dibayar
kalau kerjaan tsb tidak diselesaikan waktu deadline
• Cara mengurutkan job supaya meminimalkan total penalti?
Solusi
• Sort berdasarkan penalti terbesar
• Iterasi dari awal, jika kerjaan tsb bisa dipilih (bisa diselesaikan
sebelum deadline), langsung dipilih saja, jika tidak, abaikan.
• Kerjaan pertama dipilih, tapi kerjaan ke-2
dibuang karena tidak bisa diselesaikan.
• Kerjaan 3 & 4 dipilih.
• Kerjaan 5 dibuang
• Kerjaan 6 dipilih
• Perhatikan bahwa total penalti dari suatu permutasi
ditentukan dari subset kerjaan yang bisa diselesaikan
tepat waktu
• Pembuktian kalau permutasi dari kerjaan itu matroid:
• Jika X adalah set dari kerjaan yang valid dan X’
adalah subset dari X, maka X’ pasti juga valid
• Jika X, Y valid dan |Y| = |X| + 1, akan dibuktikan
bahwa ada a dalam Y– X sehingga X U {a} itu juga
valid. Asumsikan kerjaan tsb diurutkan berdasarkan
deadline. Mis. a = kerjaan terakhir dari Y yang blm
dipilih di dalam X, maka a bisa dimasukkan ke X