Dalam konteks greedy, kita selalu memilih opsi yang paling menguntungkan saat ini
tanpa mempertimbangkan konsekuensi di masa depan. Ini mirip dengan mengambil
sejumlah uang tunai yang tersedia dari mesin ATM tanpa memikirkan bagaimana
pengeluaran itu akan memengaruhi saldo akhir .
1. Huffman Coding
Digunakan dalam kompresi data. Ini adalah metode yang efisien untuk mengurangi
ukuran data dengan mengassign kode biner yang lebih pendek untuk karakter yang lebih
sering muncul dalam teks.
2. Activity Selection
Algoritma ini digunakan dalam manajemen waktu dan penjadwalan. Ketika Anda memiliki
sejumlah kegiatan dengan waktu mulai dan selesai yang berbeda, algoritma ini
membantu Anda memilih sejumlah kegiatan yang tidak saling tumpang tindih untuk
mendapatkan jadwal yang paling efisien.
3. Kruskal Algorithm
Digunakan dalam masalah pohon minimal (Minimum Spanning Tree) pada grafik. Ini
membantu menemukan subset dari semua edge dalam grafik yang membentuk pohon
tanpa siklus dengan total bobot yang minimal.
4. Prim’s Algorithm
Seperti Kruskal, Prim’s Algorithm juga digunakan dalam masalah pohon minimal, tetapi
fokus pada membangun pohon dari satu simpul awal dengan memilih edge terkecil yang
terhubung.
# Contoh penggunaan
items = [(2, 10), (3, 5), (5, 15), (7, 7), (1, 6)]
capacity = 15
result, total = fractional_knapsack(items, capacity)
print("Barang yang dipilih:", result)
print("Total nilai yang diperoleh:", total)
Kelebihan:
1. Sederhana dan Cepat: Algoritma greedy relatif mudah dipahami dan diimplementasikan,
dan sering kali memiliki kinerja yang cepat.
2. Solusi Terdekat: Algoritma ini cenderung menghasilkan solusi yang cukup mendekati
optimal dalam waktu yang singkat.
Kelemahan:
1. Tidak Selalu Optimal: Algoritma greedy tidak selalu menghasilkan solusi optimal. Ada
kasus di mana solusi yang dihasilkan jauh dari solusi terbaik.
2. Pemilihan Kriteria: Kegagalan dalam pemilihan kriteria rakus yang tepat dapat
mengakibatkan hasil yang tidak optimal.
3. Pengabaian Konsekuensi Masa Depan: Algoritma ini tidak mempertimbangkan
konsekuensi jangka panjang dari setiap langkah, sehingga dapat menghasilkan solusi
yang suboptimal dalam beberapa kasus.
Menurut Kamus Bahasa Inggris Oxford, "serakah" berarti memiliki keinginan berlebihan
terhadap sesuatu tanpa mempertimbangkan akibat atau kerusakan yang ditimbulkan.
Dalam ilmu komputer, algoritma serakah adalah algoritma yang menemukan solusi suatu
masalah dalam waktu sesingkat mungkin. Ia memilih jalur yang tampaknya optimal pada
saat ini tanpa memperhatikan optimalisasi keseluruhan solusi yang akan dibentuk.
Edsger Dijkstra, seorang ilmuwan komputer dan matematikawan yang ingin menghitung
pohon merentang minimum, memperkenalkan istilah “Algoritma Greedy”. Prim dan
Kruskal menemukan teknik pengoptimalan untuk meminimalkan biaya grafik.
Ada dua pendekatan untuk menyelesaikan masalah ini: pendekatan serakah atau tidak
serakah.
Contoh grafik
Grafik ini terdiri dari bobot yang berbeda dan kita perlu mencari nilai maksimumnya. Kami
akan menerapkan dua pendekatan pada grafik untuk mendapatkan solusinya.
Pendekatan Serakah
Pada gambar di bawah, suatu graf memiliki bilangan yang berbeda-beda pada simpulnya
dan algoritma ini dimaksudkan untuk memilih simpul dengan bilangan terbesar.
Dimulai dari simpul 6, lalu dihadapkan pada dua keputusan – mana yang lebih besar, 3
atau 4? Algoritme mengambil 4, dan kemudian dihadapkan pada keputusan lain – mana
yang lebih besar, 14 atau 11. Algoritme memilih 14, dan algoritme berakhir.
Di sisi lain ada simpul berlabel 20 tetapi melekat pada simpul 3 yang tidak dianggap
serakah sebagai pilihan terbaik. Penting untuk memilih kriteria yang tepat untuk membuat
setiap keputusan segera.
Dimulai dari simpul 6, lalu dihadapkan pada dua keputusan – mana yang lebih besar, 3
atau 4? Algoritme mengambil 4, dan kemudian dihadapkan pada keputusan lain – yang
lebih besar, 14 atau 11. Algoritme memilih 14 dan mengesampingkannya.
Kemudian menjalankan prosesnya lagi, dimulai dari simpul 6. Ia memilih simpul dengan
3 dan memeriksanya. 20 melekat pada simpul 3 dan proses berhenti. Sekarang ia
membandingkan dua hasil – 20 dan 14. 20 lebih besar, sehingga ia memilih titik (3) yang
mempunyai bilangan terbesar dan prosesnya berakhir.
Algoritma ini cepat dan efisien dengan kompleksitas waktu O(n log n) atau O(n). Oleh
karena itu diterapkan dalam memecahkan masalah berskala besar.
Pencarian solusi optimal dilakukan tanpa pengulangan – algoritma berjalan satu kali.
Apakah Anda memerlukan pilihan terbaik saat ini dari masalah tersebut?
Prosedur
Anggaplah Anda mempunyai masalah dengan sekumpulan angka dan Anda perlu
mencari nilai minimumnya.
Anda memulainya dengan mendefinisikan batasan, yang dalam hal ini adalah mencari
nilai minimum. Kemudian setiap angka akan dipindai dan diperiksa pada setiap batasan
yang menjadi syarat yang harus dipenuhi. Jika kondisinya benar, nomor tersebut dipilih
dan dikembalikan sebagai solusi akhir.
Pertama, kita mengurutkan aktivitas dan waktu mulai dalam urutan menaik menggunakan
waktu selesai masing-masing aktivitas.
Kemudian kita mulai dengan memilih aktivitas pertama. Kami membuat daftar baru untuk
menyimpan aktivitas yang dipilih.
Untuk memilih aktivitas selanjutnya, kita membandingkan waktu selesai aktivitas terakhir
dengan waktu mulai aktivitas berikutnya. Jika waktu mulai aktivitas berikutnya lebih besar
dari waktu selesai aktivitas terakhir, maka dapat dipilih. Jika tidak, kita lewati ini dan
periksa yang berikutnya.
Proses ini diulangi sampai semua aktivitas diperiksa. Solusi terakhir adalah daftar berisi
kegiatan-kegiatan yang dapat dilakukan.
Tabel di bawah ini menunjukkan daftar kegiatan serta waktu mulai dan selesai.
Langkah pertama adalah mengurutkan waktu selesai dalam urutan menaik dan mengatur
aktivitas berdasarkan hasilnya.
Pindah ke aktivitas berikutnya, kita periksa waktu selesainya “Pekerjaan Rumah” (5) yang
merupakan aktivitas terakhir yang dipilih dan waktu dimulainya “Makalah Semester”
(4). Untuk memilih suatu aktivitas, waktu mulai aktivitas berikutnya harus lebih besar atau
sama dengan waktu selesai. (4) kurang dari (5), jadi kita lewati aktivitas dan lanjutkan ke
aktivitas berikutnya.
Kegiatan selanjutnya “Presentasi” mempunyai waktu mulai (6) dan lebih lama
dibandingkan waktu selesai (5) “Pekerjaan Rumah”. Jadi kami memilihnya dan
menambahkannya ke daftar aktivitas pilihan kami.
Untuk kegiatan selanjutnya kita melakukan pengecekan yang sama. Waktu selesai
“Presentasi” adalah (10), waktu mulai “Latihan Bola Voli” adalah (10). Kami melihat
bahwa waktu mulai sama dengan waktu selesai yang memenuhi salah satu kondisi, jadi
kami memilihnya dan menambahkannya ke daftar aktivitas pilihan kami.
Lanjut ke kegiatan selanjutnya, waktu selesai latihan “Bola Voli” adalah (12) dan waktu
mulai “kuliah Biologi” adalah (13). Kami melihat waktu mulai lebih besar daripada waktu
selesai jadi kami memilihnya.
Untuk aktivitas terakhir kita, waktu mulai “Hangout” adalah (7) dan waktu selesai aktivitas
terakhir “Kuliah Biologi” adalah (14), 7 kurang dari 14, jadi kita tidak bisa memilih aktivitas
tersebut. Karena kita berada di akhir daftar aktivitas, prosesnya berakhir.
Hasil akhir kami adalah daftar kegiatan pilihan yang dapat kami lakukan tanpa tumpang
tindih waktu: {Pekerjaan Rumah, Presentasi, Latihan Bola Voli, Kuliah Biologi}.
selected_activity =[]
start_position = 0
Berikut tabel kerangka data yang menampilkan data asli:
Original Info
tem = 0
for i in range(0 , len(data['finish_time'])):
for j in range(0 , len(data['finish_time'])):
if data['finish_time'][i] < data['finish_time'][j]:
tem = data['activity'][i] , data['finish_time'][i] , data['start_time'][i]
data['activity'][i] , data['finish_time'][i] , data['start_time'][i] = data['activity'][j] ,
data['finish_time'][j] , data['start_time'][j]
data['activity'][j] , data['finish_time'][j] , data['start_time'][j] = tem
Pada kode di atas, kita menginisialisasi <tem>ke nol. Kami tidak menggunakan metode
bawaan untuk mengurutkan waktu selesai. Kami menggunakan dua loop untuk
mengaturnya dalam urutan menaik. <i>dan <j>mewakili indeks dan memeriksa apakah
nilainya <data['finish_time'][i]> kurang dari <data['finish_time'][j]>.
Jika kondisinya benar, <tem>simpan nilai elemen di <i>posisi dan tukar elemen terkait.
Sekarang kita print hasil akhirnya, inilah yang kita dapatkan:
# Results
# The student can work on the following activities: ['Homework', 'Presentation', 'Volleyball
practice', 'Biology lecture']
Inilah tampilannya secara keseluruhan:
data = {
"start_time": [2 , 6 , 4 , 10 , 13 , 7],
"finish_time": [5 , 10 , 8 , 12 , 14 , 15],
"activity": ["Homework" , "Presentation" , "Term paper" , "Volleyball practice" , "Biology
lecture" , "Hangout"]
}
selected_activity =[]
start_position = 0
# sorting the items in ascending order with respect to finish time
tem = 0
for i in range(0 , len(data['finish_time'])):
for j in range(0 , len(data['finish_time'])):
if data['finish_time'][i] < data['finish_time'][j]:
tem = data['activity'][i] , data['finish_time'][i] , data['start_time'][i]
data['activity'][i] , data['finish_time'][i] , data['start_time'][i] = data['activity'][j] ,
data['finish_time'][j] , data['start_time'][j]
data['activity'][j] , data['finish_time'][j] , data['start_time'][j] = tem
selected_activity.append(data['activity'][start_position])
for pos in range(len(data['finish_time'])):
if data['start_time'][pos] >= data['finish_time'][start_position]:
selected_activity.append(data['activity'][pos])
start_position = pos
Tujuannya adalah untuk mengisi ransel dengan barang-barang yang mempunyai nilai
total tertinggi dan tidak melebihi kapasitas berat maksimum.
Skenario: Di toko perhiasan, ada barang yang terbuat dari emas, perak, dan
kayu. Barang yang paling mahal adalah emas, diikuti perak, dan kemudian kayu. Jika
pencuri perhiasan datang ke toko, mereka mengambil emas karena mereka akan
mendapat untung paling besar.
Pencuri mempunyai tas (ransel) untuk menaruh barang-barang tersebut. Namun apa
yang dapat dibawa oleh pencuri ada batasnya karena barang-barang tersebut bisa
menjadi berat. Idenya adalah memilih barang yang menghasilkan keuntungan tertinggi
dan muat di dalam tas (ransel) tanpa melebihi berat maksimumnya.
Langkah pertama adalah mencari rasio nilai terhadap berat semua benda untuk
mengetahui pecahan apa yang ditempati masing-masing benda.
Kami kemudian mengurutkan rasio ini dalam urutan menurun (dari tertinggi ke
terendah). Dengan cara ini kita dapat memilih rasio dengan angka tertinggi terlebih
dahulu dengan mengetahui bahwa kita akan mendapat untung.
Saat kami memilih rasio tertinggi, kami menemukan bobot yang sesuai dan
menambahkannya ke ransel. Ada syarat yang harus diperiksa.
Kondisi 1 : Jika barang yang ditambahkan mempunyai berat lebih kecil dari berat
maksimum ransel, maka barang yang ditambahkan lebih banyak hingga jumlah semua
barang di dalam tas sama dengan berat maksimum ransel.
Kondisi 2 : Jika jumlah berat barang di dalam tas lebih dari kapasitas maksimum ransel,
kita mencari pecahan dari barang terakhir yang ditambahkan. Untuk mencari pecahan,
kita melakukan hal berikut:
Kami menemukan jumlah sisa berat barang di ransel. Jumlahnya harus kurang dari
kapasitas maksimum.
Kita cari selisih antara kapasitas maksimum ransel dan jumlah sisa berat barang dan
membaginya dengan berat barang terakhir yang ditambahkan.
Contoh Praktis:
Katakanlah kapasitas maksimal ransel adalah 17, dan tersedia tiga item. Item pertama
adalah emas, item kedua adalah perak, dan item ketiga adalah kayu.
Rasio terbesar adalah 5 dan kami mencocokkannya dengan bobot yang sesuai “6”. Ini
menunjuk ke perak.
Silver kita masukkan ke dalam knapsack terlebih dahulu dan bandingkan dengan berat
maksimum yaitu 17. 6 kurang dari 17 jadi kita harus menambah item lagi. Kembali ke
rasio, yang terbesar kedua adalah “4” dan setara dengan berat “10” yang mengacu pada
emas.
Sekarang, kita masukkan emas ke dalam ransel, tambahkan berat perak dan emas, dan
bandingkan dengan berat ransel. (6 + 10 = 16). Saat memeriksanya terhadap bobot
maksimum, kami melihat bahwa bobotnya lebih ringan. Jadi kita bisa mengambil item
lain. Kita kembali ke daftar rasio dan mengambil angka terbesar ke-3 yaitu “3” dan sesuai
dengan “2” yang menunjuk pada kayu.
Ketika kita menambahkan kayu ke dalam ransel, berat totalnya adalah (6 +10+2 = 18)
tetapi itu lebih besar dari berat maksimum kita yaitu 17. Kita mengeluarkan kayu dari
ransel dan tersisa emas dan perak. Jumlah keduanya adalah 16 dan kapasitas
maksimalnya adalah 17. Jadi kita membutuhkan bobot 1 agar sama. Sekarang kita
terapkan kondisi 2 yang dibahas di atas untuk mencari fraksi kayu yang dapat
dimasukkan ke dalam ransel.
Penjelasan mengisi sisa ruang di ransel dengan pecahan kayu
Sekarang ranselnya sudah terisi.
for i in range(len(ratio)):
for j in range(i + 1 , len(ratio)):
if ratio[i] < ratio[j]:
ratio[i] , ratio[j] = ratio[j] , ratio[i]
data['weight'][i] , data['weight'][j] = data['weight'][j] , data['weight'][i]
data['profit'][i] , data['profit'][j] = data['profit'][j] , data['profit'][i]
Setelah berat dan keuntungan diurutkan, kami mulai memilih barang dan memeriksa
kondisinya. Kami mengulang panjang rasio untuk menargetkan indeks setiap item dalam
daftar. Catatan: semua item dalam rasio diurutkan dari yang terbesar hingga yang
terkecil, sehingga item pertama adalah nilai maksimum dan item terakhir adalah nilai
minimum.
for i in range(len(ratio)):
Item pertama yang kita pilih memiliki rasio tertinggi di antara item lainnya dan berada di
indeks 0. Sekarang setelah bobot pertama dipilih, kami memeriksa apakah bobotnya
kurang dari bobot maksimum. Jika sudah, kita tambahkan barang hingga berat totalnya
sama dengan berat ransel. Item kedua yang kita pilih mempunyai rasio tertinggi kedua
diantara item lainnya dan berada pada indeks 1, susunannya adalah urutan
pemilihannya.
Untuk setiap bobot yang dipilih, kami menambahkannya ke selected_wt variabel dan
keuntungannya yang sesuai ke max_profitvariabel.
if selected_wt + data['weight'][i] <= max_weight:
selected_wt += data['weight'][i]
max_profit += data['profit'][i]
Bila jumlah bobot yang dipilih dalam ransel melebihi bobot maksimum, kita mencari
pecahan bobot item terakhir yang ditambahkan agar total bobot yang dipilih sama dengan
bobot maksimum. Caranya dengan mencari selisih antara max_weightdan jumlah bobot
yang dipilih dibagi dengan bobot item terakhir yang ditambahkan.
Keuntungan akhir yang diperoleh dari pecahan yang dibawa ditambahkan ke
variabel max_profit. Kemudian kami mengembalikannya max_profitsebagai hasil akhir.
else:
frac_wt = (max_weight - selected_wt) / data['weight'][i]
frac_value = data['profit'][i] * frac_wt
max_profit += frac_value
selected_wt += (max_weight - selected_wt)
print(max_profit)
Menyatukan semuanya:
data = {
"weight": [10 , 6 , 2],
"profit":[40 , 30 ,6]
}
max_weight = 17
selected_wt = 0
max_profit = 0
# finds ratio
ratio = [int(data['profit'][i] / data['weight'][i]) for i in range(len(data['profit']))]
# sort ratio in descending order, rearranges weight and profit in order of the sorted ratio
for i in range(len(ratio)):
for j in range(i + 1 , len(ratio)):
if ratio[i] < ratio[j]:
ratio[i] , ratio[j] = ratio[j] , ratio[i]
data['weight'][i] , data['weight'][j] = data['weight'][j] , data['weight'][i]
data['profit'][i] , data['profit'][j] = data['profit'][j] , data['profit'][i]
# checks if selected weight with the highest ratio is less than the maximum weight, if so it
adds it to knapsack and stores the profit, select the next item.
# else the sum of the selected weights is more than max weight, finds fraction
for i in range(len(ratio)):
if selected_wt + data['weight'][i] <= max_weight:
selected_wt += data['weight'][i]
max_profit += data['profit'][i]
else:
frac_wt = (max_weight - selected_wt) / data['weight'][i]
frac_value = data['profit'][i] * frac_wt
max_profit += frac_value
selected_wt += (max_weight - selected_wt)
print(f"The maximum profit that can be made from each item is: {round(max_profit , 2)}
euros")
# Result
# The maximum profit that can be made from each item is: 73.0 euros