Pemrograman Kompetitif Dasar Full C++
Pemrograman Kompetitif Dasar Full C++
1/22
Perkenalan
Mulai dari bab ini, seluruh kode program akan dituliskan dalam
pseudocode.
2/22
Pseudocode
3/22
Contoh Pseudocode
insertionSort(A)
1 for i = 2 to A.length
2 j =i
3 while (j > 1) and (A[j] < A[j − 1])
4 swap(A[j], A[j − 1])
5 j = j −1
4/22
Pseudocode (lanj.)
5/22
Tentang Pemrograman Kompetitif
Pemrograman Kompetitif
Adalah penyelesaian soal yang terdefinisi dengan jelas dengan
menulis program komputer dalam batasan-batasan tertentu
(memori dan waktu).
6/22
Tentang Pemrograman Kompetitif (lanj.)
7/22
Tentang Pemrograman Kompetitif (lanj.)
8/22
Contoh Soal Pemrograman Kompetitif
9/22
Contoh Soal Pemrograman Kompetitif (lanj.)
10/22
Solusi Naif
11/22
Solusi Naif (lanj.)
12/22
Solusi yang Lebih Baik
13/22
Solusi yang Lebih Baik (lanj.)
14/22
Solusi yang Lebih Baik (lanj.)
15/22
Solusi yang Lebih Baik (lanj.)
16/22
Solusi yang Lebih Baik (lanj.)
17/22
Solusi yang Lebih Baik (lanj.)
• Secara umum, banyaknya pembagi dari:
(1 + p1 ) × (1 + p2 ) × (1 + p3 ) × ... × (1 + pk )
18/22
Ajang Pemrograman Kompetitif
19/22
Manfaat Pemrograman Kompetitif
20/22
Dan Tentunya...
21/22
Penutup
22/22
Matematika Diskret Dasar
1/43
Pendahuluan
2/43
Matematika Diskret
3/43
Bagian 1
Arimetika Modular
4/43
Konsep Modulo
5/43
Sifat-Sifat Modulo
6/43
Aplikasi Modulo
7/43
Aplikasi Modulo (lanj.)
Solusi:
modularFactorial(n, k)
1 result = 1
2 for i = 1 to n
3 result = (result × i) mod k
4 return result
8/43
Hati-Hati!
• Aritmetika modular tidak serta-merta bekerja pada
pembagian.
• ba mod n 6= a mod n
b mod n mod n.
12 12 mod 6
• Contoh: 4 mod 6 6= 4 mod 6 mod 6.
a × b −1 mod n
9/43
Bagian 2
Bilangan Prima
10/43
Konsep Bilangan Prima
Bilangan Prima
Bilangan bulat positif yang tepat memiliki dua faktor (pembagi),
yaitu 1 dan dirinya sendiri.
Contoh: 2, 3, 5, 13, 97.
Bilangan Komposit
Bilangan yang memiliki lebih dari dua faktor.
Contoh: 6, 14, 20, 25.
11/43
Uji Keprimaan
12/43
Uji Keprimaan (lanj.)
13/43
Uji Keprimaan (lanj.)
isPrimeNaive(n)
1 if n ≤ 1
2 return false
3 for i = 2 to n − 1
4 if n mod i == 0
5 return false
6 return true
14/43
Uji Keprimaan (lanj.)
15/43
Uji Keprimaan (lanj.)
isPrimeSqrt(n)
1 if n ≤ 1
2 return false
3 i =2
4 while i × i ≤ n
5 if n mod i == 0
6 return false
7 i = i +1
8 return true
16/43
Bagian 3
Prime Generation
(Pembangkitan Bilangan Prima)
17/43
Solusi Naif
18/43
Solusi Naif (lanj.)
simplePrimeGeneration(N)
1 primeList = {}
2 for i = 2 to N
3 if isPrimeSqrt(i)
4 primeList = primeList ∪ {i}
5 return primeList
19/43
Sieve of Eratosthenes
20/43
Sieve of Eratosthenes (lanj.)
21/43
Prosedur Sieve of Eratosthenes
22/43
Implementasi Sieve of Eratosthenes
23/43
Implementasi Sieve of Eratosthenes (lanj.)
sieveOfEratosthenes(N)
1 // Siapkan array boolean eleminated berukuran N
2 // Inisialisasi array eleminated dengan false
3 primeList = {}
4 for i = 2 to n
5 if not eleminated[i]
6 primeList = primeList ∪ {i}
7 j = i ×i
8 while j ≤ n
9 eleminated[j] = true
10 j = j +i
11 return primeList
24/43
Implementasi Sieve of Eratosthenes (lanj.)
25/43
Bagian 4
26/43
Faktorisasi Prima
27/43
FPB dan KPK
a×b
• Terdapat pula sifat KPK (a, b) = FPB(a,b) .
28/43
Algoritma Euclid
29/43
Algoritma Euclid (lanj.)
euclid(a, b)
1 if b == 0
2 return a
3 else
4 return euclid(b, a mod b)
30/43
Algoritma Euclid (lanj.)
• Sangat pendek!
• Anda dapat menghemat waktu pengetikan kode dalam
melakukan pencarian FPB dengan algoritma ini.
• Jika Anda tertarik dengan pembuktiannya, baca lebih lanjut di
tautan Wikipedia ini.
31/43
Bagian 5
32/43
Pigeonhole Principle
33/43
Pigeonhole Principle (lanj.)
• Terkesan sederhana?
• Simak contoh aplikasi prinsip ini.
34/43
Contoh Soal PHP
35/43
Analisis Contoh Soal PHP
36/43
Analisis Contoh Soal PHP (lanj.)
• Mari kita coba mengerjakan versi lebih mudah dari soal ini:
Bagaimana jika yang diminta subbarisan, bukan subhimpunan?
• Anggap array A dimulai dari indeks 1 (one-based).
k
P
• Misalkan kita memiliki fungsi sum(k) = A[i].
i=1
• Untuk sum(0), sesuai definisi nilainya adalah 0.
37/43
Analisis Contoh Soal PHP (lanj.)
r
P
• Perhatikan bahwa A[i] = sum(r ) − sum(l − 1).
i=l
38/43
Analisis Contoh Soal PHP (lanj.)
• Observasi 1:
Ada N kemungkinan nilai (sum(x) mod N), yaitu [0..N − 1].
• Observasi 2:
Ada N + 1 nilai x untuk (sum(x) mod N), yaitu untuk
x ∈ [0..N].
39/43
Analisis Contoh Soal PHP (lanj.)
Observasi 3:
• Ada N + 1 kemungkinan nilai x
• Ada N kemungkinan nilai sum(x) mod N
• Pasti ada a dan b, sehingga
sum(b) mod N = sum(a) mod N
• Subbarisan yang menjadi solusi adalah A[a + 1..b].
40/43
Analisis Contoh Soal PHP (lanj.)
41/43
Implementasi
findDivisibleSubsequence(A, N)
1 // Inisialisasi array sum[0..N] dengan 0
2 // Isikan nilai sum[i] dengan (A[1] + A[2] + ... + A[i])
3 // Inisialisasi array seenInIndex[0..N − 1] dengan −1
4 for i = 0 to N
5 if seenInIndex[sum[i] mod N] == −1
6 seenInIndex[sum[i] mod N] = i
7 else
8 a = seenInIndex[sum[i] mod N]
9 b=i
10 return [a + 1, a + 2, ..., b]
42/43
Penutup
43/43
Matematika Diskret Dasar:
Kombinatorika
1/48
Pendahuluan
2/48
Bagian 1
3/48
Contoh Soal 1
• Terdapat 3 buah kota yaitu A, B, dan C.
• Kota A dan kota B terhubung oleh 3 jalur berbeda yaitu e1 ,
e2 , dan e3 .
• Sedangkan kota B dan kota C terhubung oleh 2 jalur berbeda
yaitu e4 dan e5 .
• Berapa banyak cara berbeda untuk menuju kota C dari kota
A?
• Ilustrasi:
e1 e4
e2
A e3
B e5
C
4/48
Solusi Awal
• Apabila kita hitung satu per satu, maka cara yang berbeda
untuk menuju kota C dari kota A adalah sebagai berikut:
• Melalui jalur e1 kemudian jalur e4
• Melalui jalur e1 kemudian jalur e5
• Melalui jalur e2 kemudian jalur e4
• Melalui jalur e2 kemudian jalur e5
• Melalui jalur e3 kemudian jalur e4
• Melalui jalur e3 kemudian jalur e5
• Dengan kata lain, terdapat 6 cara berbeda untuk menuju kota
C dari kota A.
• Tetapi, apabila jumlah kota dan jalur yang ada sangatlah
banyak, kita tidak mungkin menulis satu per satu cara yang
berbeda. Karena itulah kita gunakan aturan perkalian.
5/48
Aturan Perkalian
6/48
Solusi dengan Aturan Perkalian
7/48
Contoh Soal 2
• Contoh soal ini merupakan lanjutan dari Contoh Soal 1.
• Deskripsi soal, jumlah kota dan jalur serta susunan jalur yang
ada sama persis dengan soal tersebut.
• Tambahkan 1 jalur lagi, yaitu e6 yang menghubungkan kota A
dan C.
• Berapa banyak cara berbeda untuk menuju kota C dari kota
A?
• Ilustrasi:
e1 e4
e2
A e3
B e5
C
e6
8/48
Analisis Contoh Soal
• Dengan mencoba satu persatu setiap cara, maka terdapat 7
cara yang berbeda, yaitu 6 cara sesuai dengan soal
sebelumnya, ditambah dengan menggunakan jalur e6 .
• Apabila kita menggunakan aturan perkalian, maka didapatkan
banyak cara yang berbeda adalah 3 × 2 × 1 = 6 yang mana
jawaban tersebut tidaklah tepat.
• Kita tidak dapat menggunakan aturan perkalian dalam
permasalahan ini, karena antara perjalanan dari kota A
menuju kota C melalui kota B dengan tanpa melalui kota B
merupakan 2 proses yang berbeda.
• Oleh karena itu, kita dapat menggunakan aturan
penjumlahan.
9/48
Aturan Penjumlahan
10/48
Solusi dengan Aturan Penjumlahan
11/48
Hati-Hati!
12/48
Bagian 2
Permutasi
13/48
Perkenalan Permutasi
14/48
Notasi Faktorial
15/48
Aturan Pembagian
16/48
Contoh Aturan Pembagian
17/48
Contoh Aturan Pembagian (lanj.)
18/48
Contoh Soal 1
19/48
Solusi Awal
20/48
Solusi Secara Umum
21/48
Permutasi
22/48
Contoh Soal 2
23/48
Solusi Awal
24/48
Solusi Secara Umum
25/48
Permutasi Elemen Berulang
26/48
Contoh Soal 3
27/48
Solusi Awal
28/48
Solusi Secara Umum
29/48
Permutasi Siklis
30/48
Bagian 3
Kombinasi
31/48
Contoh Soal 1
32/48
Solusi Awal
• Soal ini berbeda dengan permutasi, karena susunan ABC dan
BAC merupakan susunan yang sama, yaitu 1 tim terdiri dari
A, B, dan C.
• Apabila kita anggap bahwa mereka merupakan susunan yang
120
berbeda, maka banyaknya susunan tim adalah P25 = 2 = 60.
• Untuk setiap susunan yang terdiri dari anggota yang sama
akan terhitung 6 susunan berbeda yang mana seharusnya
hanya dihitung sebagai 1 susunan yang sama.
• Contoh: ABC, ACB, BAC, BCA, CAB, CBA merupakan 1
susunan yang sama.
• Oleh karena itu dengan aturan pembagian, banyaknya
60
susunan tim yang berbeda adalah 6 = 10 susunan berbeda.
33/48
Solusi Secara Umum
34/48
Kombinasi
35/48
Contoh Soal 2
• Pak Dengklek ingin membeli kue pada toko kue yang menjual
3 jenis kue, yaitu rasa coklat, stroberi, dan kopi.
• Apabila Pak Dengklek ingin membeli 4 buah kue, maka berapa
banyak kombinasi kue berbeda yang Pak Dengklek dapat beli?
36/48
Analisis Contoh Soal
37/48
Solusi
• Kita dapat membagi 4 kue tersebut menjadi 3 bagian. Untuk
mempermudah ilustrasi tersebut, kita gunakan lambang o
yang berarti kue, dan | yang berarti pembatas.
• Bagian kiri merupakan kue A, bagian tengah merupakan kue
B, dan bagian kanan merupakan kue C.
• Contoh: (o|o|oo) menyatakan 1 kue A, 1 kue B, dan 2 kue
C.
• Contoh lain: (oo|oo|) menyatakan 2 kue A, 2 kue B, dan 0
kue C.
• Dengan kata lain, semua susunan yang mungkin adalah
(oooo||), (ooo|o|), (oo|oo|), ..., (||oooo) yang tidak
6!
lain merupakan C26 = 4!×2! = 15 susunan berbeda.
38/48
Solusi Secara Umum
39/48
Kombinasi dengan Perulangan
40/48
Bagian 4
Segitiga Pascal
41/48
Segitiga Pascal
42/48
Analisis
43/48
Analisis (lanj.)
44/48
Analisis (lanj.)
45/48
Implementasi Segitiga Pascal (lanj.)
segitiga pascal(N)
1 // Sediakan array 2-dimensi C berukuran (N + 1) × (N + 1)
2 for i = 0 to N
3 C [i][0] = 1
4 for j = 0 to i − 1
5 C [i][j] = C [i − 1][j − 1] + C [i − 1][j]
6 C [i][i] = 1
46/48
Penggunaan Segitiga Pascal
47/48
Penutup
48/48
Brute Force
1/20
Pendahuluan
2/20
Konsep
3/20
Konsep (lanj.)
4/20
Sifat Brute Force
5/20
Soal: Subset Sum
Batasan:
• 1 ≤ N ≤ 15
• 1 ≤ K ≤ 109
• 1 ≤ ai ≤ 109
6/20
Solusi
7/20
Performa?
8/20
Implementasi
solve(i, sum)
1 if i > N
2 return (sum == K )
solveSubsetSum()
1 return solve(1, 0)
9/20
Optimisasi
10/20
Solusi Teroptimisasi
solve(i, sum)
1 if i > N
2 return (sum == K )
3 if sum > K
4 return false
11/20
Pruning
12/20
Pruning (lanj.)
13/20
Soal: Mengatur Persamaan
14/20
Solusi Sederhana
countTriplets()
1 count = 0
2 for i = 1 to N
3 for j = 1 to N
4 for k = 1 to N
5 p = ai
6 q = aj
7 r = ak
8 if (p + q + r ) == 0
9 count = count + 1
10 return count
15/20
Solusi Sederhana (lanj.)
16/20
Observasi
17/20
Solusi Lebih Baik
countTripletsFast()
1 count = 0
2 for i = 1 to N
3 for j = 1 to N
4 p = ai
5 q = aj
6 r = −(p + q)
7 if exists(r )
8 count = count + 1
9 return count
18/20
Solusi Lebih Baik (lanj.)
19/20
Penutup
20/20
Divide and Conquer
1/37
Perkenalan
2/37
Konsep
3/37
Ilustrasi Konsep
divide
conquer
combine
4/37
Studi Kasus 1: Merge Sort
5/37
Contoh Eksekusi Merge Sort
6/37
Contoh Eksekusi Merge Sort (lanj.)
5 2 7 6 1 8 9 3
5 2 7 6 1 8 9 3
7/37
Contoh Eksekusi Merge Sort (lanj.)
5 2 7 6 1 8 9 3
5 2 7 6 1 8 9 3
8/37
Contoh Eksekusi Merge Sort (lanj.)
5 2 7 6 1 8 9 3
5 2 7 6 1 8 9 3
9/37
Contoh Eksekusi Merge Sort (lanj.)
5 2 7 6 1 8 9 3
10/37
Contoh Eksekusi Merge Sort (lanj.)
5 2 7 6 1 8 9 3
2 5 6 7 1 8 3 9
11/37
Contoh Eksekusi Merge Sort (lanj.)
Gabungkan lagi.
2 5 6 7 1 8 3 9
2 5 6 7 1 3 8 9
12/37
Contoh Eksekusi Merge Sort (lanj.)
2 5 6 7 1 3 8 9
1 2 3 5 6 7 8 9
13/37
Menggabungkan Dua Array Terurut
2 5 6 7 1 3 8 9
14/37
Menggabungkan Dua Array Terurut (lanj.)
2 5 6 7 1 3 8 9
15/37
Menggabungkan Dua Array Terurut (lanj.)
Ulangi hal serupa sampai salah satu atau kedua array habis.
2 5 6 7 3 8 9
16/37
Menggabungkan Dua Array Terurut (lanj.)
5 6 7 3 8 9
1 2
17/37
Menggabungkan Dua Array Terurut (lanj.)
5 6 7 8 9
1 2 3
18/37
Menggabungkan Dua Array Terurut (lanj.)
6 7 8 9
1 2 3 5
19/37
Menggabungkan Dua Array Terurut (lanj.)
7 8 9
1 2 3 5 6
20/37
Menggabungkan Dua Array Terurut (lanj.)
Ketika salah satu array telah habis, array yang masih bersisa
tinggal ditempelkan di akhir array gabungan.
8 9
1 2 3 5 6 7
21/37
Menggabungkan Dua Array Terurut (lanj.)
1 2 3 5 6 7 8 9
22/37
Analisis Menggabungkan Dua Array Terurut
23/37
Analisis Algoritma Merge Sort
24/37
Analisis Algoritma Merge Sort (lanj.)
1
2
3
4
25/37
Analisis Algoritma Merge Sort (lanj.)
26/37
Contoh Implementasi
Mengurutkan arr [left..right]:
27/37
Contoh Implementasi (lanj.)
Menggabungkan arr [aLeft..aRight] dengan arr [bLeft..bRight] yang
telah terurut:
28/37
Contoh Implementasi (lanj.)
5 ...
6 // Selama kedua subarray masih ada isinya, ambil yang terkecil
7 while (aIndex ≤ aRight) and (bIndex ≤ bRight)
8 if temp[aIndex] < temp[bIndex]
9 arr [tIndex] = temp[aIndex]
10 aIndex = aIndex + 1
11 else
12 arr [tIndex] = temp[bIndex]
13 bIndex = bIndex + 1
14 tIndex = tIndex + 1
15 ...
29/37
Contoh Implementasi (lanj.)
14 ...
15 // Masukkan subarray yang masih bersisa
16 // Hanya salah satu dari kedua while ini yang akan dieksekusi
17 while (aIndex ≤ aRight)
18 arr [tIndex] = temp[aIndex]
19 aIndex = aIndex + 1
20 tIndex = tIndex + 1
21 while (bIndex ≤ bRight)
22 arr [tIndex] = temp[bIndex]
23 bIndex = bIndex + 1
24 tIndex = tIndex + 1
25 // selesai penggabungan
30/37
Catatan Tentang Merge Sort
31/37
Studi Kasus 2: Mencari Nilai Terbesar
32/37
Studi Kasus 2: Mencari Nilai Terbesar (lanj.)
33/37
Contoh Implementasi
34/37
Analisis Algoritma Mencari Nilai Terbesar
O(1)
O(1) O(1)
35/37
Analisis Algoritma Mencari Nilai Terbesar (lanj.)
36/37
Penutup
37/37
Divide and Conquer:
Quicksort
1/31
Pengenalan
2/31
Konsep
5 2 7 6 1 8 9 3
3/31
Konsep (lanj.)
2 1 3 5 7 6 8 9
4/31
Konsep (lanj.)
2 1 3 5 7 6 8 9
5/31
Konsep (lanj.)
6/31
Partisi
7/31
Partisi (lanj.)
8/31
Partisi Hoare
9/31
Partisi Hoare (lanj.)
Misalkan pivot = 5.
Mulai dengan dua variabel penunjuk, kiri dan kanan di
ujung-ujung array .
2 5 7 4 6 1 3 8 9
^
kiri
^
kanan
10/31
Partisi Hoare (lanj.)
2 5 7 4 6 1 3 8 9
^
kiri
^
kanan
11/31
Partisi Hoare (lanj.)
2 5 7 4 6 1 3 8 9
^
kiri
^
kanan
12/31
Partisi Hoare (lanj.)
2 5 7 4 6 1 3 8 9
^ kanan
kiri
^
13/31
Partisi Hoare (lanj.)
2 5 3 4 6 1 7 8 9
^ kanan
kiri
^
14/31
Partisi Hoare (lanj.)
2 5 3 4 6 1 7 8 9
^ ^
kiri kanan
15/31
Partisi Hoare (lanj.)
2 5 3 4 6 1 7 8 9
^ ^
kiri kanan
16/31
Partisi Hoare (lanj.)
2 5 3 4 6 1 7 8 9
^ ^
kanan kiri
17/31
Partisi Hoare (lanj.)
2 5 3 4 1 6 7 8 9
^ ^
kanankiri
18/31
Partisi Hoare (lanj.)
2 5 3 4 1 6 7 8 9
^ ^
kanan kiri
19/31
Implementasi Partisi Hoare
20/31
Analisis Algoritma Partisi Hoare
21/31
Integrasi ke Quicksort
Setelah kita mengimplementasikan algoritma partisi,
mengintegrasikan ke quicksort cukup mudah.
quicksort(arr [], left, right)
1 if left ≥ right
2 // Tidak ada elemen yang perlu diurutkan
3 else
4 pivot = arr [(left + right) div 2]
7 quicksort(left, pRight)
8 quicksort(pLeft, right)
22/31
Analisis Algoritma Quicksort
23/31
Analisis Algoritma Quicksort (lanj.)
24/31
Analisis Algoritma Quicksort: Kasus Terbaik
1
2
3
4
25/31
Analisis Algoritma Quicksort: Kasus Rata-Rata
• Pada kebanyakan kasus, ukuran hasil partisi berbeda.
• Secara rata-rata kompleksitasnya masih dapat dianggap
O(N log N).
26/31
Analisis Algoritma Quicksort: Kasus Terburuk
• Kasus paling buruk: ukuran hasil partisi sangat timpang.
• Akibatnya, kedalaman rekursif mendekati N.
• Kompleksitasnya menjadi O(N 2 ).
27/31
Analisis Algoritma Quicksort (lanj.)
28/31
Pemilihan Pivot
29/31
Stable Sort
30/31
Penutup
31/31
Greedy
1/32
Pendahuluan
2/32
Greedy
3/32
Konsep Greedy
4/32
Contoh Soal: Activity Selection
5/32
Contoh Activity Selection
1 2 3 4 5 6 7 8 9
6/32
Solusi Activity Selection
• Misalkan kegiatan pertama yang kita ikuti adalah kegiatan
ke-x.
• Kegiatan selanjutnya yang diikuti haruslah memiliki waktu
awal ≥ ax .end.
• Lebih jauh lagi, ternyata kita mendapat persoalan yang
serupa, hanya saja ukurannya lebih kecil.
• Dengan kata lain, kita memperoleh subpersoalan.
sub-persoalan
^ ^
ax.start ax.end
7/32
Solusi Activity Selection (lanj.)
8/32
Memilih Aktivitas Pertama
9/32
Memilih Aktivitas Pertama (lanj.)
10/32
Memilih Aktivitas Pertama (lanj.)
Memilih aktivitas dengan waktu akhir paling awal:
• Dengan memilih aktivitas yang selesai lebih awal, kita
mempunyai sisa waktu lebih banyak untuk aktivitas lainnya.
• Tanpa peduli kapan aktivitas ini mulai atau berapa durasinya,
memilih yang selesai lebih awal pasti menguntungkan.
• Pilihan ini adalah merupakan greedy choice, yang selalu
menghasilkan solusi optimal.
11/32
Penyelesaian Activity Selection
• Kini kita dapat menentukan aktivitas yang akan diikuti
pertama kali.
• Selanjutnya kita mendapatkan subpersoalan, yang ternyata
dapat diselesaikan dengan cara serupa!
sub-persoalan
^ ^
ax.start ax.end
12/32
Contoh Eksekusi Activity Selection
13/32
Contoh Eksekusi Activity Selection (lanj.)
14/32
Contoh Eksekusi Activity Selection (lanj.)
15/32
Contoh Eksekusi Activity Selection (lanj.)
16/32
Contoh Eksekusi Activity Selection (lanj.)
17/32
Contoh Eksekusi Activity Selection (lanj.)
18/32
Contoh Eksekusi Activity Selection (lanj.)
19/32
Contoh Eksekusi Activity Selection (lanj.)
20/32
Contoh Eksekusi Activity Selection (lanj.)
Selesai!
Tidak ada cara lain yang memberikan hasil lebih optimal.
21/32
Implementasi Solusi Activity Selection
solveActivitySelection(a[], N)
1 // Urutkan a secara menaik berdasarkan a[i].end
2 sortByEndingTime(a, N)
3 selectedCount = 0
4 startTime = 1
5 for i = 1 to N
6 if (a[i].start >= startTime)
7 selectedCount = selectedCount + 1
8 startTime = a[i].end + 1
9 return selectedCount
22/32
Analisis Kompleksitas
23/32
Selingan
24/32
Permasalahan pada Algoritma Greedy
25/32
Permasalahan pada Algoritma Greedy
26/32
Permasalahan pada Algoritma Greedy (lanj.)
27/32
Permasalahan pada Algoritma Greedy (lanj.)
28/32
Permasalahan pada Algoritma Greedy (lanj.)
29/32
Permasalahan pada Algoritma Greedy (lanj.)
30/32
Saran
31/32
Penutup
32/32
Dynamic Programming
1/41
Pendahuluan
2/41
Motivasi
3/41
Solusi Greedy
4/41
Solusi Greedy (lanj.)
5/41
Observasi
6/41
Observasi (lanj.)
7/41
Solusi Rekursif
8/41
Solusi Rekursif (lanj.)
9/41
Solusi Rekursif (lanj.)
10/41
Solusi Rekursif (lanj.)
11/41
Implementasi Solusi Rekursif
Kita implementasikan f (x) sebagai fungsi solve(x):
solve(x)
1 if (x == 0)
2 return 0
3
4 best = ∞
5 for k = 1 to M
6 if (ak ≤ x)
7 best = min(best, solve(x − ak ) + 1)
8 return best
12/41
Solusi Rekursif (lanj.)
Mari kita lihat pohon rekursi yang dihasilkan oleh fungsi f .
Berikut untuk f (12) dengan nominal koin 1, 6, dan 10 rupiah.
f (12)
13/41
Solusi Rekursif (lanj.)
14/41
Solusi Rekursif (lanj.)
15/41
Optimisasi
Jika diperhatikan, ternyata banyak f (x) yang dihitung berkali-kali.
Sebagai contoh, f (5) dan f (4).
f (12)
16/41
Optimisasi (lanj.)
17/41
Solusi Rekursif dengan Memoisasi
solve(x)
1 if (x == 0)
2 return 0
3 if computed[x]
4 return memo[x] // Langsung kembalikan
5
6 best = ∞
7 for k = 1 to M
8 if (ak ≤ x)
9 best = min(best, solve(x − ak ) + 1)
10 computed[x] = true // Tandai bahwa sudah pernah dihitung
11 memo[x] = best
12 return best
18/41
Solusi Rekursif dengan Memoisasi (lanj.)
19/41
Dynamic Programming
20/41
Dynamic Programming
21/41
Top-Down
22/41
Bottom Up
23/41
Solusi dengan Bottom-Up
Secara bottom-up, kita hitung semua nilai f (x) untuk
semua nilai x dari 0 sampai N secara menaik.
Nilai dari f (x) disimpan dalam array f [x].
solve()
1 f [0] = 0
2 for x = 1 to N
3 best = ∞
4 for k = 1 to M
5 if (ak ≤ x)
6 best = min(best, f [x − ak ] + 1)
7 f [x] = best
8 return f [N]
24/41
Kompleksitas?
25/41
Mengisi ”Tabel”
x 0 1 2 3 4 5 6 7 8 9 10 11 12
f (x)
26/41
Mengisi ”Tabel” (lanj.)
x 0 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 0
27/41
Mengisi ”Tabel” (lanj.)
x 0 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 0 1
28/41
Mengisi ”Tabel” (lanj.)
Hal serupa terjadi ketika kita mengisi f (2), f (3), f (4), danf (5).
Satu-satunya pilihan adalah menukarkan dengan koin 1, karena
kita tidak bisa menggunakan koin 6 atau 10.
x 0 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 0 1 2 3 4 5
29/41
Mengisi ”Tabel” (lanj.)
f (6) = min(f (6 − 1) + 1, f (6 − 6) + 1)
= min(f (5) + 1, f (0) + 1)
= min(5 + 1, 0 + 1)
= min(6, 1)
=1
30/41
Mengisi ”Tabel” (lanj.)
x 0 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 0 1 2 3 4 5 1
31/41
Mengisi ”Tabel” (lanj.)
x 0 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 0 1 2 3 4 5 1 2 3 4
32/41
Mengisi ”Tabel” (lanj.)
33/41
Mengisi ”Tabel” (lanj.)
x 0 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 0 1 2 3 4 5 1 2 3 4 1
34/41
Mengisi ”Tabel” (lanj.)
x 0 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 0 1 2 3 4 5 1 2 3 4 1 2
35/41
Mengisi ”Tabel” (lanj.)
Terakhir, isi f (12).
36/41
Mengisi ”Tabel” (lanj.)
x 0 1 2 3 4 5 6 7 8 9 10 11 12
f (x) 0 1 2 3 4 5 1 2 3 4 1 2 2
37/41
Top-Down dan Bottom-Up
Top-down
• Sebuah transformasi natural dari formula rekursif, biasanya
mudah diimplementasikan.
• Urutan pengisian tabel tidak penting.
• Hanya menghitung nilai dari fungsi jika hanya diperlukan.
• Ketika seluruh tabel memo pada akhirnya terisi, bisa saja lebih
lambat karena adanya overhead pemanggilan fungsi.
38/41
Top-Down dan Bottom-Up (lanj.)
Bottom-up
• Tidak mengalami perlambatan dari overhead pemanggilan
fungsi.
• Memungkinkan penggunaan teknik DP lanjutan seperti flying
table, kombinasi dengan struktur data tree, dsb.
• Harus memikirkan urutan pengisian nilai tabel.
• Semua tabel harus diisi nilainya walaupun tidak dibutuhkan
akhirnya.
39/41
Top-Down dan Bottom-Up (lanj.)
40/41
Penutup
41/41
Dynamic Programming:
Studi Kasus
1/29
Pendahuluan
2/29
Contoh Soal 1: Knapsack
3/29
Observasi
4/29
Formulasi
5/29
Formulasi Rekurens
6/29
Formulasi Rekurens (lanj.)
7/29
Formulasi Rekurens (lanj.)
8/29
Formulasi Base Case
9/29
Formulasi Akhir
10/29
Analisis Kompleksitas
11/29
Solusi Top-Down
Kita implementasikan dp(i, c) sebagai fungsi solve(i, c):
solve(i, c)
1 if (i == 0)
2 return 0
3 if computed[i][c]
4 return memo[i][c]
5 best = solve(i − 1, c)
6 if (c ≥ w [i])
7 best = max(best, solve(i − 1, c − w [i]) + v [i])
8 computed[i][c] = true
9 memo[i][c] = best
10 return best
12/29
Solusi Bottom-Up
solve()
1 // Base case
2 for c = 0 to G
3 dp[0][c] = 0
11 return dp[N][G ]
13/29
Contoh Soal 2: Memotong Kayu
Diadopsi dari UVa 10003 - Cutting Sticks
14/29
Contoh Soal 2: Memotong Kayu (lanj.)
2 4 7
15/29
Contoh Soal 2: Memotong Kayu (lanj.)
Kita bisa memotong pada titik 2, titik 4, lalu titik 7 dan
memerlukan usaha 10 + 8 + 6 = 24.
2 4 7
+10
+8
+6
16/29
Contoh Soal 2: Memotong Kayu (lanj.)
Cara lain adalah memotong pada titik 4, titik 2, lalu titik 7 dan
memerlukan usaha 10 + 4 + 6 = 20.
2 4 7
+10
+4
+6
17/29
Solusi Greedy?
18/29
Observasi
19/29
Formulasi Rekurens
20/29
Formulasi Rekurens (lanj.)
21/29
Formulasi Base Case
22/29
Formulasi Akhir
Dapat dirumuskan:
0, l >r
dp(l, r ) =
minl≤m≤r dp(l, m − 1) + dp(m + 1, r ) + (Lr +1 − Ll−1 ), l ≤ r
23/29
Analisis Kompleksitas
24/29
Solusi Top-Down
Kita implementasikan dp(l, r ) sebagai fungsi solve(l, r ):
solve(l, r )
1 if (l > r )
2 return 0
3 if computed[l][r ]
4 return memo[l][r ]
5
6 best = ∞
7 cost = L[r + 1] − L[l − 1]
8 for m = l to r
9 best = min(best, solve(l, m − 1) + solve(m + 1, r ) + cost)
10 computed[l][r ] = true
11 memo[l][r ] = best
12 return best
Jawaban akhirnya ada pada solve(1, N).
25/29
Solusi Bottom Up
solve()
1 // Base case
2 for l = 0 to N + 1
3 for r = 0 to l − 1
4 dp[l][r ] = 0
14 return dp[1][N]
26/29
Pengisian ”Tabel” DP
27/29
Pengisian ”Tabel” DP (lanj.)
28/29
Penutup
29/29
Struktur Data Dasar
1/47
Pendahuluan
2/47
Tentang Struktur Data
Struktur Data
Merupakan tata cara untuk merepresentasikan dan menyimpan
data, sehingga mendukung operasi terhadap data tersebut secara
efisien.
3/47
Kilas Balik: Array
4/47
Kilas Balik: Array (lanj.)
5/47
Kilas Balik: Array (lanj.)
6/47
Bagian 1
Linked List
7/47
Mengenal Linked List
Linked list terdiri dari kumpulan node.
data next
8/47
Mengenal Linked List (lanj.)
head
30 1 20 16
9/47
Jenis Linked List
10/47
Struktur Doubly Linked List
head tail
30 1 20 16
11/47
Linked List dan Array
• Pada doubly linked list, biasanya kita hanya memiliki referensi
ke head dan tail.
• Untuk mengakses elemen ke-x dari linked list, kita dapat
melakukannya dengan:
get(head, x)
1 current = head
2 for i = 2 to x
3 current = current.next
4 return current
12/47
Linked List dan Array (lanj.)
13/47
Menyisipkan Elemen Linked List
newNode
20
node
... 1 16 ...
14/47
Menyisipkan Elemen Linked List (lanj.)
newNode
20
node
... 1 16 ...
15/47
Menyisipkan Elemen Linked List (lanj.)
newNode
20
node
... 1 16 ...
16/47
Menyisipkan Elemen Linked List (lanj.)
17/47
Menghapus Elemen Linked List
Diberikan node yang bukan head maupun tail, hapus dari linked
list.
node
... 1 20 16 ...
18/47
Menghapus Elemen Linked List (lanj.)
node
... 1 20 16 ...
19/47
Menghapus Elemen Linked List (lanj.)
3. Hapus node.
node
... 1 16 ...
20/47
Menghapus Elemen Linked List (lanj.)
21/47
Rangkuman
22/47
Mengenal Stack
• Stack dapat dimisalkan seperti tumpukan piring pada
umumnya.
• Jika terdapat piring baru yang ingin dimasukkan, maka piring
tersebut masuk dari paling atas.
• Jika sebuah piring akan diambil dari tumpukan, maka yang
diambil juga piring yang paling atas.
23/47
Mengenal Stack (lanj.)
• Struktur data stack menyimpan informasi dalam bentuk
tumpukan.
• Informasi yang baru dimasukkan ke paling atas tumpukan.
• Hanya informasi paling atas yang bisa diakses/dihapus pada
setiap waktunya.
• Oleh karena itu struktur data stack disebut memiliki sifat
LIFO (Last In First Out).
24/47
Operasi pada Stack
25/47
Aplikasi Stack
26/47
Aplikasi Stack Lainnya
27/47
Aplikasi Stack Lainnya (lanj.)
28/47
Eksekusi Ekspresi Postfix
Ekspresi: 1 2 3 + − 4 ×
1. Push angka 1, stack: [1].
2. Push angka 2, stack: [1, 2].
3. Push angka 3, stack: [1, 2, 3].
4. Ditemukan +:
• Pop dua kali, didapat nilai 2 dan 3, stack: [1].
• Operasikan 2 + 3, dan push, stack: [1, 5]
5. ...
29/47
Eksekusi Ekspresi Postfix (lanj.)
Ekspresi: 1 2 3 + − 4 ×
5. Ditemukan -:
• Pop dua kali, didapat nilai 1 dan 5, stack: [].
• Operasikan 1 - 5, dan push, stack: [-4]
6. Push angka 4, stack: [-4, 4].
7. Ditemukan ×:
• Pop dua kali, didapat nilai -4 dan 4, stack: [].
• Operasikan -4 × 4, dan push, stack: [-16]
Jadi 1 2 3 + − 4 × = −16
30/47
Implementasi Stack
31/47
Alternatif Implementasi Stack
32/47
Alternatif Implementasi Stack (lanj.)
initializeStack(maxSize)
1 // Buat array stack berukuran maxSize
2 topOfStack = 0
push(item)
1 topOfStack = topOfStack + 1
2 stack[topOfStack] = item
pop()
1 topOfStack = topOfStack − 1
top()
1 return stack[topOfStack]
33/47
Alternatif Implementasi Stack (lanj.)
34/47
Bagian 2
Stack
35/47
Contoh Soal
36/47
Pembahasan Soal
37/47
Bagian 3
Queue
38/47
Mengenal Queue
39/47
Mengenal Queue (lanj.)
• Struktur data queue menyimpan informasi dalam bentuk
antrean.
• Informasi yang baru dimasukkan ke paling belakang antrean.
• Hanya informasi paling depan yang bisa diakses/dihapus pada
setiap waktunya.
• Oleh karena itu struktur data queue disebut memiliki sifat
FIFO (First In First Out).
40/47
Operasi Queue
41/47
Aplikasi Queue
42/47
Implementasi Queue
43/47
Alternatif Implementasi Queue
44/47
Alternatif Implementasi Queue (lanj.)
initializeQueue(maxSize)
1 // Buat array queue berukuran maxSize
2 head = 1
3 tail = 0
push(item)
1 tail = tail + 1
2 queue[tail] = item
pop()
1 head = head + 1
front()
1 return queue[head]
45/47
Alternatif Implementasi Queue (lanj.)
46/47
Penutup
47/47
Perkenalan Graf
1/47
Pendahuluan
2/47
Motivasi
3/47
Pertanyaan
4/47
Bagian 1
Perkenalan Graf
5/47
Mengenal Graf
E B
D C
6/47
Mengenal Graf (lanj.)
• Edge merupakan penghubung antar node.
• Degree suatu node merupakan jumlah edge yang terhubung
pada node tersebut
• Pada contoh ilustrasi berikut, degree node A = 4, degree
node B = 3, dan degree node C = 5.
E B
D C
7/47
Jenis Graf
Berdasarkan hubungan antar node:
• Graf tak berarah: edge dari A ke B dapat ditelusuri dari A
ke B dan B ke A.
• Graf berarah: edge dari A ke B hanya dapat ditelusuri dari
dari A ke B.
A A
B D D
B
C C
Graf tak berarah dan graf berarah
8/47
Jenis Graf (lanj.)
Berdasarkan bobot dari edge:
• Graf tak berbobot, yaitu graf dengan edge yang bobotnya
seragam dan hanya bermakna terdapat hubungan antar node.
• Graf berbobot, yaitu graf dengan edge yang dapat memiliki
bobot berbeda-beda. Bobot pada edge ini bisa jadi berupa
biaya, jarak, atau waktu yang harus ditempuh jika
menggunakan edge tersebut.
A 1
A
B B 5
D 3
D
2
C C
Graf tak berbobot dan graf berbobot
9/47
Jenis Graf (lanj.)
Tentu saja, suatu graf dapat memiliki kombinasi dari sifat-sifat
tersebut.
Misalnya graf berbobot berarah:
1 A
3 5
B 2 D
8
C
10/47
Representasi Graf pada Pemrograman
11/47
Adjacency Matrix
A B C D A
A 0 1 1 1
B 1 0 0 0 D
C 0 0 0 1 B
D 0 0 0 0 C
12/47
Adjacency Matrix (lanj.)
A B C D A
A ∞ 3 2 5 1
3 5
B 1 ∞ ∞ ∞ 2 D
C ∞ ∞ ∞ 8 B 8
D ∞ ∞ ∞ ∞ C
13/47
Analisis Adjacency Matrix
14/47
Kekurangan Adjacency Matrix
15/47
Adjacency List
A [B, C , D] A
B [A]
C [D] D
D [] B
C
16/47
Adjacency List (lanj.)
1 A
A [< B, 3 >, < C , 2 >, < D, 5 >]
B [< A, 1 >] 3 5
B 2 D
C [< D, 8 >] 8
D [] C
17/47
Implementasi Adjacency List
18/47
Implementasi Adjacency List (lanj.)
• List yang dimaksud bisa berupa linked list atau resizable array.
• Bagi pengguna C++ atau Java, struktur list yang dapat
digunakan adalah vector atau ArrayList.
• Untuk pengguna C atau Pascal, struktur linked list perlu
dibuat terlebih dahulu.
19/47
Analisis Adjacency List
20/47
Edge List
< A, B >, A
< A, C >,
< A, D >, D
< B, A >, B
< C, D > C
21/47
Edge List (lanj.)
< A, B, 3 >, A
< A, C , 2 >, 1
3 5
< A, D, 5 >, 2 D
< B, A, 1 >, B 8
< C , D, 8 > C
22/47
Implementasi Edge List
23/47
Analisis Edge List
24/47
Keuntungan dan Kerugian Representasi Graf
Untuk graf dengan V node dan E edge:
25/47
Bagian 2
Penjelajahan Graf
26/47
Penjelajahan Graf
27/47
Penjelajahan Graf (lanj.)
28/47
DFS: Depth-First Search
Penelusuran dilakukan terhadap node yang lebih dalam terlebih
dahulu (depth-first).
Sebagai contoh, misal terdapat graf berikut:
29/47
DFS: Depth-First Search (lanj.)
Penelusuran secara DFS akan dilakukan dengan cara berikut:
2 6 7
3 4 8 11
5 9 10
30/47
Penelusuran DFS
1
2 6 7
3 4 8 11
5 9 10
DFS(curNode)
1 print ”mengunjungi curNode”
2 visited[curNode] = true
3 for each adjNode ∈ adj(curNode)
4 if not visited[adjNode]
5 DFS(adjNode)
32/47
Implementasi DFS (Stack)
DFS()
1 // Inisialisasi stack sebagai stack kosong.
2 stack.push(initialNode)
3 visited[initialNode] = true
4 while not stack.empty ()
5 curNode = stack.top()
6 stack.pop()
7 print ”mengunjungi curNode”
8 visited[adjNode] = true
9 for each adjNode ∈ adj(curNode)
10 if not visited[adjNode]
11 stack.push(adjNode)
33/47
BFS: Breadth-First Search
Penelusuran node pada graf dilakukan lapis demi lapis.
Semakin dekat suatu node dengan node awal, node tersebut akan
dikunjungi terlebih dahulu.
2 3 4
5 6 7 8
9 10 11
34/47
Penelusuran BFS
2 3 4
5 6 7 8
9 10 11
35/47
Implementasi BFS
BFS()
1 // Inisialisasi queue sebagai queue kosong.
2 queue.push(initialNode)
3 visited[initialNode] = true
4 while not queue.empty ()
5 curNode = queue.front()
6 queue.pop()
7 print ”mengunjungi curNode”
8 for each adjNode ∈ adj(curNode)
9 if not visited[adjNode]
10 visited[adjNode] = true
11 queue.push(adjNode)
36/47
Analisis Kompleksitas
37/47
Contoh Permasalahan (lanj.)
38/47
Solusi
39/47
Implementasi Solusi
shortestPath(A, B)
1 // Inisialisasi queue sebagai queue kosong.
2 // Inisialisasi array visitTime dengan -1.
3 queue.push(A)
4 visitTime[A] = 0
5 while not queue.empty ()
6 curNode = queue.front()
7 queue.pop()
8 for each adjNode ∈ adj(curNode)
9 // Jika adjNode belum pernah dikunjungi...
10 if visitTime[adjNode] == −1
11 visitTime[adjNode] = visitTime[curNode] + 1
12 queue.push(adjNode)
13 return visitTime[B]
40/47
Bagian 3
Macam-Macam Graf
41/47
Macam-Macam Graf
42/47
Tree
• Tree merupakan bentuk khusus dari graf.
• Seluruh node pada tree terhubung (tidak ada node yang tidak
dapat dikunjungi dari node lain) dan tidak terdapat cycle.
• Banyaknya edge dalam sebuah tree pasti V − 1, dengan V
adalah banyaknya node.
43/47
Contoh Tree
F F
B G
E A
B A D I
D C E H
C
44/47
Directed Acyclic Graph
• directed acyclic graph (DAG) merupakan bentuk khusus dari
directed graf.
• DAG tidak memiliki cycle.
• Berbeda dengan tree yang mana setiap node harus dapat
dikunjungi dari node lainnya, sifat tersebut tidak berlaku pada
DAG.
F
B G
A D
C
E
45/47
Contoh Directed Acyclic Graph
F
B G C
A D A B E
C
E D F
46/47
Penutup
47/47
Struktur Data NonLinear:
Disjoint Set
1/25
Pendahuluan
2/25
Motivasi
3/25
Contoh Perilaku
4/25
Contoh Perilaku (lanj.)
• ...
• check(1, 2): laporkan bahwa 1 dan 2 berada di kelompok
yang sama.
• join(3, 5), kini kelompok yang ada adalah [1, 2, 4], [3, 5].
• join(2, 3), kini kelompok yang ada adalah [1, 2, 3, 4, 5].
• check(1, 5): laporkan bahwa 1 dan 5 berada di kelompok
yang sama.
5/25
Solusi Sederhana
6/25
Analisis Solusi Sederhana
7/25
Masalah Solusi Sederhana
8/25
Disjoint Set
9/25
Ide Dasar
10/25
Cara Kerja Disjoint Set
• Setiap elemen perlu menyimpan pointer ke elemen yang
merupakan perwakilannya.
• Pointer yang ditunjuk oleh suatu perwakilan kelompok adalah
dirinya sendiri.
11/25
Cara Kerja Disjoint Set (lanj.)
12/25
Inisialisasi Disjoint Set
initialize()
1 for i = 0 to N − 1 // Indeks elemen dimulai dari 0 (zero-based)
2 par [i] = i
13/25
Operasi Join
join
14/25
Operasi Join (lanj.)
• Perhatikan bahwa yang perlu diubah adalah parent dari
perwakilan kelompok suatu elemen, bukan elemen itu sendiri.
join
join
15/25
Operasi Join (Implementasi)
join(a, b)
1 repA = findRepresentative(a)
2 repB = findRepresentative(b)
3 par [repA] = repB
16/25
Operasi Join (implementasi findRepresentative)
findRepresentative(x)
1 if par [x] == x
2 return x
3 else
4 return findRepresentative(par [x])
17/25
Kekurangan findRepresentative
• Fungsi findRepresentative memiliki kompleksitas sebesar
O(L), dengan L adalah panjangnya jalur dari elemen x sampai
elemen perwakilan kelompoknya.
• Ketika L mendekati N, fungsi ini tidak efisien bila dipanggil
berkali-kali.
x
18/25
Memperbaiki findRepresentative
• Kita dapat menerapkan teknik path compression, yaitu
mengubah nilai parent dari setiap elemen yang dilalui
langsung ke elemen perwakilan kelompok.
• Hal ini menjamin untuk pemanggilan findRepresentative
berikutnya pada elemen yang bersangkutan bekerja secara
lebih efisien.
x
19/25
Implementasi Path Compression
findRepresentative(x)
1 if par [x] == x
2 return x
3 else
4 // Catat elemen representatifnya
5 par [x] = findRepresentative(par [x])
6 return par [x]
20/25
Analisis Kompleksitas findRepresentative
• Untuk disjoint set dengan N elemen, paling banyak terdapat
N parent yang dikenakan path compression.
• Apabila seluruh parent elemen sudah dikenakan path
compression, maka setiap elemen langsung menunjuk ke
elemen perwakilan kelompoknya.
• Artinya, kini fungsi findRepresentative bekerja dalam
O(1).
21/25
Analisis Kompleksitas findRepresentative (lanj.)
22/25
Analisis Kompleksitas Join
23/25
Operasi Check
check(a, b)
1 return findRepresentative(a) == findRepresentative(b)
24/25
Penutup
25/25
Struktur Data Nonlinear:
Heap
1/64
Pendahuluan
2/64
Motivasi
3/64
Motivasi
4/64
Solusi Sederhana
5/64
Analisis Solusi Sederhana
6/64
Analisis Solusi Sederhana
7/64
Masalah Solusi Sederhana
8/64
Bagian 1
Pengenalan Heap
9/64
Heap
10/64
Operasi Heap
11/64
Cara Kerja Heap
12/64
Tree
• Seperti yang telah dipelajari, tree merupakan suatu graf yang
setiap node-nya saling terhubung dan tidak memiliki cycle.
13/64
Rooted Tree
• Suatu tree yang memiliki hierarki dan memiliki sebuah akar
disebut sebagai rooted tree.
14/64
Binary Tree
• Suatu rooted tree yang setiap node-nya memiliki 0, 1, atau 2
anak disebut dengan binary tree.
15/64
Full Binary Tree
• Suatu binary tree yang seluruh node-nya memiliki 2 anak,
kecuali tingkat paling bawah yang tidak memiliki anak,
disebut dengan full binary Tree
• Bila banyaknya node adalah N, maka ketinggiannya adalah
O(log N).
16/64
Complete Binary Tree
Complete binary tree adalah binary tree yang:
• Seluruh node-nya memiliki 2 anak, kecuali tingkat paling
bawah.
• Tingkat paling bawahnya dapat terisi sebagian, tetapi harus
terisi dari kiri ke kanan.
18/64
Bukan Complete Binary Tree
Berikut juga bukan complete binary tree, sebab terdapat node
tanpa 2 anak pada tingkat bukan paling bawah.
19/64
Struktur Binary Heap
20/64
Contoh Binary Heap
7 7
5 4 6 2
1 3 4
21/64
Contoh Bukan Binary Heap
Bukan binary heap.
7 7
5 9 7 2
1 3 4
22/64
Mengapa Harus Demikian?
23/64
Operasi Push
24/64
Operasi Push
Sebagai contoh, misalkan hendak ditambahkan elemen bernilai 8
ke suatu binary heap berikut:
7 7
5 4 6 2
1 3 4
25/64
Operasi Push (lanj.)
Tambahkan node.
7 7
5 4 6 2
1 3 4 8
26/64
Operasi Push (lanj.)
Karena parent-nya memiliki nilai lebih kecil, tukar nilainya.
7 7
5 8 6 2
1 3 4 4
27/64
Operasi Push (lanj.)
Karena parent-nya masih memiliki nilai lebih kecil, tukar lagi.
8 7
5 7 6 2
1 3 4 4
28/64
Operasi Push (lanj.)
Parent-nya sudah memiliki nilai yang lebih besar.
Operasi push selesai.
8 7
5 7 6 2
1 3 4 4
29/64
Kompleksitas Push
30/64
Operasi Pop
31/64
Operasi Pop (lanj.)
Misalkan akan dilakukan pop pada heap berikut:
8 7
5 7 6 2
1 3 4 4
32/64
Operasi Pop (lanj.)
Tukar elemen pada root dengan elemen terakhir pada complete
binary tree.
8 7
5 7 6 2
1 3 4 9
33/64
Operasi Pop (lanj.)
Buang elemen terakhir.
8 7
5 7 6 2
1 3 4 9
34/64
Operasi Pop (lanj.)
Perbaiki struktur heap dengan menukar elemen pada root dengan
anaknya yang bernilai terbesar.
4 7
5 7 6 2
1 3 4
35/64
Operasi Pop (lanj.)
Karena masih terdapat anaknya yang lebih besar, tukar lagi.
7 7
5 4 6 2
1 3 4
36/64
Operasi Pop (lanj.)
Kini sudah tidak ada anak yang bernilai lebih besar, operasi pop
selesai.
7 7
5 4 6 2
1 3 4
37/64
Kompleksitas Pop
38/64
Operasi Top
39/64
Analisis Solusi dengan Heap
40/64
Bagian 2
41/64
Membuat Tree
42/64
Representasi Complete Binary Tree
43/64
Representasi Complete Binary Tree (lanj.)
0
1 2
2.0+1 2.0+2
2.1+1
3 2.1+2
4 5 2.2+1
2.1+2
2.1+1
0 1 2 3 4 5
2.0+1
2.2+1
2.0+2
44/64
Representasi Complete Binary Tree (lanj.)
• Dengan logika yang serupa, orang tua dari node ke-i adalah
node ke-b i−1
2 c.
• Apabila Anda memutuskan untuk menggunakan one-based,
berarti rumusnya menjadi:
• Anak kiri: 2i.
• Anak kanan: 2i + 1.
• Orang tua: b 2i c
• Representasi ini sangat mempermudah implementasi binary
heap.
45/64
Representasi Array
• Karena panjang array dapat bertambah atau berkurang,
diperlukan array yang ukurannya dinamis.
• Pada contoh ini, kita akan menggunakan array berukuran
statis dan sebuah variabel yang menyatakan ukuran array saat
ini.
• Berikut prosedur untuk inisialisasi, dengan asumsi maxSize
menyatakan ukuran terbesar pada heap yang mungkin.
initializeHeap(maxSize)
1 // Buat array arr berukuran maxSize
2 size = 0
*arr dan size merupakan variabel global, yaitu array dan variabel
yang menyatakan ukurannya saat ini.
46/64
Implementasi Fungsi Pembantu
Buat juga beberapa fungsi yang akan membantu mempermudah
penulisan kode.
getParent(x)
1 return floor((x − 1)/2)
getLeft(x)
1 return 2x + 1
getRight(x)
1 return 2x + 2
47/64
Implementasi Push
push(val)
1 i = size
2 arr [i] = val
3 while (i > 0) ∧ (arr [i] > arr [getParent(i)])
4 swap(arr [i], arr [getParent(i)])
5 i = getParent(i)
6 size = size + 1
48/64
Implementasi Pop
pop()
1 swap(arr [0], arr [size − 1])
2 size = size − 1
3 i =0
4 swapped = true
5 while swapped
6 maxIdx = i
7 if (getLeft(i) < size) ∧ (arr [maxIdx] < arr [getLeft(i)])
8 maxIdx = getLeft(i)
9 if (getRight(i) < size) ∧ (arr [maxIdx] < arr [getRight(i)])
10 maxIdx = getRight(i)
11 swap(arr [i], arr [maxIdx])
12 swapped = (maxIdx 6= i) // true bila terjadi pertukaran
13 i = maxIdx
49/64
Implementasi Top
top()
return arr [size − 1]
50/64
Pembuatan Heap
51/64
Pembuatan Heap Secara Efisien
52/64
Operasi Heapify
heap heap
53/64
Operasi Heapify (lanj.)
54/64
Operasi Heapify (lanj.)
heapify(rootIdx)
1 i = rootIdx
2 swapped = true
3 while swapped
4 maxIdx = i
5 if (getLeft(i) < size) ∧ (arr [maxIdx] < arr [getLeft(i)])
6 maxIdx = getLeft(i)
7 if (getRight(i) < size) ∧ (arr [maxIdx] < arr [getRight(i)])
8 maxIdx = getRight(i)
9 swap(arr [i], arr [maxIdx])
10 swapped = (maxIdx 6= i) // true bila terjadi pertukaran
11 i = maxIdx
55/64
Operasi Heapify (lanj.)
pop()
1 swap(arr [0], arr [size − 1])
2 size = size − 1
3 heapify(0)
56/64
Kompleksitas Heapify
57/64
Implementasi Pembangunan Heap Secara Efisien
• Setelah memahami heapify, kita dapat menulis prosedur
pembangunan heap dari array A berisi N elemen secara
efisien.
• Elemen terakhir yang berada pada tingkat kedua paling bawah
dapat ditemukan dengan mudah, yaitu elemen dengan indeks
N/2 dibulatkan ke bawah dan dikurangi 1.
makeHeap(N)
1 initializeHeap(N)
2 for i = 0 to N − 1
3 arr [size] = A[i]
4 size = size + 1
5 for i = bN/2c − 1 to 0
6 heapify(i)
58/64
Ilustrasi Pembangunan Heap Secara Efisien
4 3
2 1
59/64
Analisis Pembangunan Heap Secara Efisien
60/64
Catatan Implementasi
61/64
Manfaat Heap
62/64
Library Heap
63/64
Penutup
64/64
Aplikasi Struktur Data Nonlinear:
Heapsort
1/8
Pendahuluan
2/8
Kilas Balik
3/8
Kilas Balik (lanj.)
4/8
Heapsort
5/8
Analisis Heapsort
6/8
Keuntungan Heapsort
7/8
Penutup
8/8
Komputasi Geometri Dasar
1/21
Pendahuluan
2/21
Titik
3/21
Garis
• Garis merupakan himpunan seluruh titik (x, y ), yang
memenuhi suatu persamaan Ax + By = C , dengan A, B, dan
C merupakan suatu bilangan riil.
• Bentuk lain dari persamaan garis yang umum adalah
y = mx + c, dengan m dan c suatu bilangan riil.
y
y=0.5x-2
4=x-2y
4 x
-2
4/21
Garis (lanj.)
• Untuk merepresentasikan garis, kita dapat membuat kelompok
data yang menyimpan nilai < A, B, C >, atau < m, c >,
bergantung pada persamaan yang Anda gunakan.
• Apabila ditelusuri, kedua persamaan ini sebenarnya berkaitan:
Ax + By = C
By = C − Ax
C A
y = − x
B
B
A C
y = − x+
B B
A
• Jadi m = − B dan c = CB .
5/21
Garis Vertikal
• Hati-hati saat merepresentasikan garis vertikal, misalnya
x = 3.
• Representasi Ax + By = C dapat merepresentasikannya, yaitu
dengan A = 1, B = 0, C = 3.
x
x=3
6/21
Garis Vertikal (lanj.)
7/21
Segmen Garis
• Segmen garis merupakan garis yang terdefinisi dari suatu
titik (x1 , y1 ) ke titik (x2 , y2 )
• Perhatikan bahwa berbeda dengan segmen garis, garis
memiliki panjang yang tak berhingga.
• Segmen garis dapat direpresentasikan dengan dua titik, yaitu
ujung-ujungnya.
y
B(5,4)
A(-2,2)
4=x-2y
4 x
-2
8/21
Jarak Euclidean
• Jarak Euclidean adalah definisi jarak yang umum digunakan
pada bidang 2 dimensi atau ruang 3 dimensi.
• Jarak pada bidang 2 dimensi dari dua titik A(x, y) dan B(x, y)
adalah: p
dist(A, B) = (A.x − B.x)2 + (A.y − B.y )2
• Anda dapat menggunakan rumus ini untuk mengetahui
panjang dari segmen garis.
y
B(6,3)
82+62=10
6 x
A(-2,-3)
8
9/21
Segitiga
10/21
Teorema Pythagoras
a c
11/21
Luas Segitiga
• Rumus klasik dari luas segitiga dengan panjang alas a dan
tinggi t adalah:
a×t
L=
2
12/21
Luas Segitiga (Rumus Heron)
• Ada kalanya kita tidak tahu tinggi dari segitiga, sehingga
rumus sebelumnya tidak dapat digunakan.
• Alternatif lain adalah menggunakan rumus Heron, yaitu:
p
L= s(s − a)(s − b)(s − c)
a+b+c
dengan s =
2
b c
13/21
Sudut Segitiga
22.5
67.5
90
14/21
Segi-N
135 67.5
45 112.5
15/21
Lingkaran
• Lingkaran dengan titik pusat (xp , yp ) dan jari-jari r merupakan
himpunan seluruh titik (x, y ) yang memenuhi
(x − xp )2 + (y − yp )2 = r 2 .
y
r
(xp, yp)
x
16/21
Properti Lingkaran
17/21
Tentang Pi
• Pi merupakan konstanta dalam matematika, dan digunakan
dalam pencarian luas atau keliling lingkaran.
22
• Hati-hati! Nilai pi tidak sama dengan .
7
22
• Penggunaan hanyalah aproksimasi dari nilai pi yang
7
sesungguhnya.
π = 3.14159265359..
22
= 3.14285714285..
7
18/21
Tentang Pi (lanj.)
19/21
Pesan Tentang Presisi
20/21
Penutup
21/21
Memenangkan Kompetisi
1/13
Kompetisi
2/13
Mengenali Medan
3/13
Perhitungan Poin
Ada dua jenis cara perhitungan poin yang umum digunakan pada
kompetisi pemrograman:
• IOI-style
Anda bisa mendapatkan poin secara parsial, tergantung
subtask yang Anda kerjakan. Waktu pengerjaan tidak
berpengaruh pada hasil akhir. IOI dan OSN menggunakan
sistem penilaian ini.
• ICPC-style
Anda harus menyelesaikan masalah secara keseluruhan.
Dengan kata lain, nilai Anda adalah 0 atau 100. Penentuan
pemenang dihitung dari total soal yang diselesaikan. Waktu
pengerjaan dihitung sebagai penalti.
4/13
Jenis Soal
5/13
Jumlah dan Tingkat Kesulitan Soal
6/13
Waktu dan Sumber Daya
7/13
Persiapan Sebelum Kompetisi
• Lakukan latihan secara berkala sebelum kompetisi. Latihan
bisa dilakukan di:
• TLX
• Codeforces
• Topcoder
• SPOJ
• COCI
• dll
• Simulasikan OSN. Bisa menyelesaikan soal setingkat OSN saja
tidak cukup.
• Anda harus dapat menyelesaikannya dalam situasi yang serupa
saat kompetisi. Buatlah simulasi OSN dengan memilih 3 buah
soal, kemudian kerjakan sebaik-baiknya selama 5 jam tanpa
bantuan.
8/13
Tips Sebelum Kompetisi
9/13
Tips Saat Kompetisi (lanj.)
10/13
Tips Saat Kompetisi (lanj.)
11/13
Tips Saat Kompetisi (lanj.)
12/13
Penutup
13/13