Anda di halaman 1dari 57

Hard DP & Hard Greedy

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;

Tambah 1 array lagi untuk simpan index” value koin yang


dipilih
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;
Terus di luar lakukan
void bt(int x)
if(x > 0) { bt(x– koin[prev[x]]); printf(koin[prev[x]]); }
Contoh Soal 2 Backtrack Solusi :
• Diberikan 1 barisan isi N bilangan bulat
• Berapa longest increasing subsequence-nya?
(strictly increasing)
• Cetak juga angka-angka yang diambil

• 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

Masalahnya = Kompleksitas memori = 2*10.000*10.000 = 2*108 (MLE)


• Perhatikan untuk mengisi f(…,i+1,...) cuma dibutuhkan
f(…, i, ...) saja
• Berarti bisa pakai flying table  pakai DP bottom-up
• Array DP-nya jadi DP[track/offtrack][prev/now][K]
• Jadi memori tinggal = 2 * 2 * 10000 = 4 * 104 (AC) 
DP Map
• Di suatu negara, keping uang sebesar X bisa ditukar
dengan keping uang sebesar X/2, X/3, dan X/5
(dibulatkan ke bawah)
• Tentukan uang maksimal yang bisa didapat jika
awalnya keping uang sebesar N
• N ≤ 109
DP(x) = 0 x=0
max(x, DP(x/2) + DP(x/3) + DP(x/5)) x>0

Cuma butuh memori :


Contoh Soal: Acorn (ICPC Singapore 2007)
• Terdapat N pohon, masing-masing ketinggiannya H
• Pada pohon ke-i, ketinggian ke-j, terdapat kacang dengan nilai kenikmatan
x[i][j]
• Seekor tupai boleh mulai dari pohon manapun, tinggi manapun, dan bisa
melompat turun (ketinggian berkurang 1)
• Jika ketika saat melompat turun mau pindah pohon, maka dia kehilangan
ketinggiannya sebesar F
• Tentukan total kenikmatan kacang yang bisa didapatkan!
• N,H,F ≤ 2000
Contoh Soal: Kingdom Division
(Petrozavodsk 2007/2008)
• Ada N titik
• Buat polyline, dari kiri ke kanan yang membelah N titik
tersebut jadi utara & selatan
• Bagi sedemikian rupa sehingga perbedaan maks
banyak titik di utara, selatan, dan tepat di perbatasan
sekecil mungkin
• N ≤ 50
Cara 1
DP(x, A, B, C) = max( |A-B|, |B-C|, |C-A| )
min(DP(next point, A+…, B+1, C+...) )

Kompleksitas = O(N5)  TLE 


Cara Optimal : kurangi state
Karena B = N – A – C
Jadi DP statenya bisa dikurangi jadi DP(x, A, C)

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

• F(n, k) = F(n, k-1) + F(n-1, k) – F(n-1, k-n)  O(nk)


Greedy
• Butuh banyak observasi
• Trik-trik :
• Sort menurut kriteria tertentu
• Bekerja dari belakang
• Pikirkan kriteria solusi optimal, coba sisihkan
kemungkinan yang tidak optimal
• Amati kasus/constraint di soal
Contoh Soal: Stick Cutting
• Kita memiliki kayu sepanjang M, dan hendak
membuat N potongan kayu
• Potongan kayu ke-i diharapkan memiliki panjang p[i]
Biaya memotong kayu sepanjang X adalah X
• Tentukan cara pemotongan paling murah untuk
menghasilkan N potongan tersebut!
• N,M≤105
• p[1]+p[2]+...+p[N] = M
Contoh Soal : Pindahan
• Ada N barang
• Barang ke – i memiliki berat B[i]
• Untuk setiap pasang barang, barang satu pasti
kelipatan dari barang yang lain
• Ada M kotak
• Kotak ke-i muat barang” dengan total berat ≤ M[i]
• Banyak barang maks yang bisa dimuat?
Observasi 1
• Sort berat barang
• Barang yang diambil pasti K barang teringan pertama
Solusi 1
• Binary search K (banyak barang teringan pertama yang
diambil)
• Pakai STL priority queue untuk simpan kotak” yg tersedia
• Mulai dari barang ke-K teringan, cari kotak terbesar dan
masukkan barang ini ke dalamnya
• Ulangi sampai barang habis
• Jika selalu ada kotak, naikkan K, jika tidak, turunkan K

• Kompleksitas O(N log2N)


Observasi 2
• Setiap barang bisa dinyatakan dalam bentuk perkalian beberapa
bilangan
• Bentuk urutan bilangan setelah di-sort:
•a
• a*b
• a*b*c
• a*b*c*d
• Jika barang dengan berat B dimasukkan ke kotak dengan
kapasitas M, bisa dianggap kita kehilangan kotak dengan
kapasitas M dan dapat kotak baru dengan kapasitas M-B
Solusi 2

• Perhatikan B[i] ≥ B[j] + B[k], untuk setiap B[i]


> B[j] dan B[i] > B[k]
• Dengan begitu, kita bisa mulai dengan
berusaha memasukkan barang ke-N hingga
barang ke-X (jalan mundur) melalui strategi
yg sama dengan solusi 1
• Jika suatu ketika barang ke-X tidak bisa dimuat ke kotak
manapun, keluarkan barang ke-N = mendapatkan kotak
baru dengan kapasitas B[N].
• Masukkan sebanyak mungkin barang ke-X sampai barang
ke-(X-p) ke dalam kotak ini
• Berhenti ketika barang ke-1 sampai barang ke-K sudah
dimasukkan --> K adalah jawabannya
• Kompleksitas = O(N log N)
Contoh Soal: Let’s Go Green (ICPC Jakarta
2012)
• Diberikan tree dengan N node
• Setiap edge ada nilai C yang berarti pada hari itu ada C
sepeda yang lewat edge tsb ( C ≤ 100 )
• Rute sepeda harus dimulai dari suatu node ke node
lainnya, tanpa bercabang
• Tentukan banyaknya rute sepeda minimal yang
dibutuhkan!
• N ≤ 105
• Pakai DFS
• Untuk greedynya perhatikan branch terbesar pada
masing” anak
• Greedy -> sebisa mungkin syarat rute branch dari
node tsb dimasukkan ke branch terbesar
• Yang perlu diperhatikan waktu proses suatu node ->
maximum dan jumlah branch pada edge node
sekarang ke node anak
• Ada 2 kondisi
• Kalau sisa dari jumlah semua branch sesudah
di-”merge” dengan branch terbesar > branch
dari node sekarang ke parent  tambahkan ke
counter answer = maximum branch – branch
dari node ke parent
• Kalau jumlah branch ≥ branch node ke parent 
tambahkan ke counter answer ceil((jumlah
branch – branch node ke parent) / 2)
Jumlah branch = 16
1 Branch maksimum = 8
Sisa branch yg blm dapat rute = 0
2 7 Branch node ke parent = 11 
11 Tidak memenuhi kondisi 1

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

Di sini yang jadi set E = edge di graph G


Set I = set dari semua kemungkinan forest dari G (ga
ada cycle)
(E, I) = matroid?
Properti 1: Untuk semua I1 dalam I, jika I2
adalah subset dari I1, maka I2 pasti di dalam I
Menghapus edge manapun dari hasil forest akan
menghasilkan forest lain
<terpenuhi>
Properti 2:
• Ambil I1, I2 terserah dengan syarat |I2| = |I1| +1
• Ada 3 kemungkinan:
• Ada edge di I2 yang punya maksimum 1 vertex yang sama
dengan vertex yang menjadi ujung dari edge di I1  Jadi I1
U { e } adalah forest  tetap masuk dalam I

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

Anda mungkin juga menyukai