#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// Struktur untuk merepresentasikan setiap item
typedef struct {
int id;
int weight;
int value;
double ratio; // Rasio Nilai/Bobot
} Item;
// Fungsi perbandingan untuk qsort
// Digunakan untuk mengurutkan item berdasarkan rasio (descending/terbesar di awal)
int compareItems( const void * a, const void * b) {
// Casting pointer void* ke pointer Item*
const Item * itemA = ( const Item * ) a;
const Item * itemB = ( const Item * ) b;
// Untuk descending order, kita kembalikan (B - A).
if ( itemA-> ratio < itemB-> ratio) return 1 ;
if ( itemA-> ratio > itemB-> ratio) return - 1 ;
return 0 ; // Rasio sama
}
/**
* @brief Menyelesaikan masalah Rational Knapsack menggunakan strategi Greedy.
*
* @param items Array item.
* @param n Jumlah item.
* @param capacity Kapasitas maksimum knapsack.
* @return double Nilai total maksimum optimal.
*/
double rational_knapsack_greedy( Item items[ ] , int n, int capacity) {
// 1. Hitung rasio Nilai/Bobot untuk setiap item
for ( int i = 0 ; i < n; i++ ) {
if ( items[ i] .weight > 0 ) {
items[ i] .ratio = ( double ) items[ i] .value / items[ i] .weight ;
} else {
items[ i] .ratio = 0.0 ;
}
}
// 2. Urutkan item berdasarkan rasio menggunakan qsort
qsort ( items
, n
, sizeof ( Item
) , compareItems
) ;
double total_value = 0.0 ;
int current_weight = 0 ;
printf ( "\n --- Proses Pengisian Knapsack (Greedy) ---\n " ) ; printf ( "Item diurutkan berdasarkan Rasio (tertinggi ke terendah).\n " ) ;
// 3. Iterasi dan ambil item
for ( int i = 0 ; i < n; i++ ) {
if ( current_weight >= capacity) {
break ; // Knapsack sudah penuh
}
int remaining_capacity = capacity - current_weight;
if ( items[ i] .weight <= remaining_capacity) {
// Kasus 1: Ambil seluruh item
current_weight += items[ i] .weight ;
total_value += items[ i] .value ;
printf ( "Mengambil Item %d (Bobot %d, Nilai %d, Rasio %.2f) secara UTUH.\n " , items[ i] .id , items[ i] .weight , items[ i] .value , items[ i] .ratio ) ;
} else {
// Kasus 2: Ambil sebagian (fraksi) dari item
double fraction = ( double ) remaining_capacity / items[ i] .weight ;
double fractional_value = fraction * items[ i] .value ;
total_value += fractional_value;
current_weight = capacity; // Knapsack menjadi penuh
printf ( "Mengambil Item %d (Bobot %d, Nilai %d, Rasio %.2f) dengan FRAKSI: %.2f%%.\n " , items[ i] .id , items[ i] .weight , items[ i] .value , items[ i] .ratio , fraction * 100 ) ;
break ; // Knapsack sudah penuh
}
}
return total_value;
}
// --- Fungsi utama untuk pengujian ---
int main( ) {
printf ( "=== Uji Coba Rational Knapsack (Bahasa C) ===\n " ) ;
// Data Uji
Item items[ ] = {
{ 1 , 2 , 10 , 0.0 } , // Rasio 5.0
{ 2 , 4 , 10 , 0.0 } , // Rasio 2.5
{ 3 , 6 , 12 , 0.0 } , // Rasio 2.0
{ 4 , 9 , 18 , 0.0 } // Rasio 2.0
} ;
int n = sizeof ( items) / sizeof ( items[ 0 ] ) ;
int capacity = 15 ;
printf ( "Kapasitas Knapsack: %d kg\n " , capacity
) ; printf ( "Daftar Item Awal:\n ID | Bobot | Nilai\n " ) ; printf ( "---|-------|-------\n " ) ; for ( int i = 0 ; i < n; i++ ) {
printf ( "%-2d | %-5d | %-5d\n " , items
[ i
] .
id , items
[ i
] .
weight , items
[ i
] .
value ) ; }
// Panggil fungsi solusi
double result = rational_knapsack_greedy( items, n, capacity) ;
// Tampilkan hasil dengan 2 angka di belakang koma
printf ( "\n --- Hasil Akhir ---\n " ) ; printf ( "Nilai Maksimum Optimal: $%.2f\n " , result
) ; printf ( "===========================================\n " ) ;
return 0 ;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPG1hdGguaD4KCi8vIFN0cnVrdHVyIHVudHVrIG1lcmVwcmVzZW50YXNpa2FuIHNldGlhcCBpdGVtCnR5cGVkZWYgc3RydWN0IHsKICAgIGludCBpZDsKICAgIGludCB3ZWlnaHQ7CiAgICBpbnQgdmFsdWU7CiAgICBkb3VibGUgcmF0aW87IC8vIFJhc2lvIE5pbGFpL0JvYm90Cn0gSXRlbTsKCi8vIEZ1bmdzaSBwZXJiYW5kaW5nYW4gdW50dWsgcXNvcnQKLy8gRGlndW5ha2FuIHVudHVrIG1lbmd1cnV0a2FuIGl0ZW0gYmVyZGFzYXJrYW4gcmFzaW8gKGRlc2NlbmRpbmcvdGVyYmVzYXIgZGkgYXdhbCkKaW50IGNvbXBhcmVJdGVtcyhjb25zdCB2b2lkICphLCBjb25zdCB2b2lkICpiKSB7CiAgICAvLyBDYXN0aW5nIHBvaW50ZXIgdm9pZCoga2UgcG9pbnRlciBJdGVtKgogICAgY29uc3QgSXRlbSAqaXRlbUEgPSAoY29uc3QgSXRlbSAqKWE7CiAgICBjb25zdCBJdGVtICppdGVtQiA9IChjb25zdCBJdGVtICopYjsKCiAgICAvLyBVbnR1ayBkZXNjZW5kaW5nIG9yZGVyLCBraXRhIGtlbWJhbGlrYW4gKEIgLSBBKS4KICAgIGlmIChpdGVtQS0+cmF0aW8gPCBpdGVtQi0+cmF0aW8pIHJldHVybiAxOwogICAgaWYgKGl0ZW1BLT5yYXRpbyA+IGl0ZW1CLT5yYXRpbykgcmV0dXJuIC0xOwogICAgcmV0dXJuIDA7IC8vIFJhc2lvIHNhbWEKfQoKLyoqCiAqIEBicmllZiBNZW55ZWxlc2Fpa2FuIG1hc2FsYWggUmF0aW9uYWwgS25hcHNhY2sgbWVuZ2d1bmFrYW4gc3RyYXRlZ2kgR3JlZWR5LgogKgogKiBAcGFyYW0gaXRlbXMgQXJyYXkgaXRlbS4KICogQHBhcmFtIG4gSnVtbGFoIGl0ZW0uCiAqIEBwYXJhbSBjYXBhY2l0eSBLYXBhc2l0YXMgbWFrc2ltdW0ga25hcHNhY2suCiAqIEByZXR1cm4gZG91YmxlIE5pbGFpIHRvdGFsIG1ha3NpbXVtIG9wdGltYWwuCiAqLwpkb3VibGUgcmF0aW9uYWxfa25hcHNhY2tfZ3JlZWR5KEl0ZW0gaXRlbXNbXSwgaW50IG4sIGludCBjYXBhY2l0eSkgewogICAgCiAgICAvLyAxLiBIaXR1bmcgcmFzaW8gTmlsYWkvQm9ib3QgdW50dWsgc2V0aWFwIGl0ZW0KICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CiAgICAgICAgaWYgKGl0ZW1zW2ldLndlaWdodCA+IDApIHsKICAgICAgICAgICAgaXRlbXNbaV0ucmF0aW8gPSAoZG91YmxlKWl0ZW1zW2ldLnZhbHVlIC8gaXRlbXNbaV0ud2VpZ2h0OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGl0ZW1zW2ldLnJhdGlvID0gMC4wOwogICAgICAgIH0KICAgIH0KCiAgICAvLyAyLiBVcnV0a2FuIGl0ZW0gYmVyZGFzYXJrYW4gcmFzaW8gbWVuZ2d1bmFrYW4gcXNvcnQKICAgIHFzb3J0KGl0ZW1zLCBuLCBzaXplb2YoSXRlbSksIGNvbXBhcmVJdGVtcyk7CgogICAgZG91YmxlIHRvdGFsX3ZhbHVlID0gMC4wOwogICAgaW50IGN1cnJlbnRfd2VpZ2h0ID0gMDsKICAgIAogICAgcHJpbnRmKCJcbi0tLSBQcm9zZXMgUGVuZ2lzaWFuIEtuYXBzYWNrIChHcmVlZHkpIC0tLVxuIik7CiAgICBwcmludGYoIkl0ZW0gZGl1cnV0a2FuIGJlcmRhc2Fya2FuIFJhc2lvICh0ZXJ0aW5nZ2kga2UgdGVyZW5kYWgpLlxuIik7CgogICAgLy8gMy4gSXRlcmFzaSBkYW4gYW1iaWwgaXRlbQogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICBpZiAoY3VycmVudF93ZWlnaHQgPj0gY2FwYWNpdHkpIHsKICAgICAgICAgICAgYnJlYWs7IC8vIEtuYXBzYWNrIHN1ZGFoIHBlbnVoCiAgICAgICAgfQoKICAgICAgICBpbnQgcmVtYWluaW5nX2NhcGFjaXR5ID0gY2FwYWNpdHkgLSBjdXJyZW50X3dlaWdodDsKCiAgICAgICAgaWYgKGl0ZW1zW2ldLndlaWdodCA8PSByZW1haW5pbmdfY2FwYWNpdHkpIHsKICAgICAgICAgICAgLy8gS2FzdXMgMTogQW1iaWwgc2VsdXJ1aCBpdGVtCiAgICAgICAgICAgIGN1cnJlbnRfd2VpZ2h0ICs9IGl0ZW1zW2ldLndlaWdodDsKICAgICAgICAgICAgdG90YWxfdmFsdWUgKz0gaXRlbXNbaV0udmFsdWU7CiAgICAgICAgICAgIAogICAgICAgICAgICBwcmludGYoIk1lbmdhbWJpbCBJdGVtICVkIChCb2JvdCAlZCwgTmlsYWkgJWQsIFJhc2lvICUuMmYpIHNlY2FyYSBVVFVILlxuIiwgCiAgICAgICAgICAgICAgICAgICBpdGVtc1tpXS5pZCwgaXRlbXNbaV0ud2VpZ2h0LCBpdGVtc1tpXS52YWx1ZSwgaXRlbXNbaV0ucmF0aW8pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIEthc3VzIDI6IEFtYmlsIHNlYmFnaWFuIChmcmFrc2kpIGRhcmkgaXRlbQogICAgICAgICAgICBkb3VibGUgZnJhY3Rpb24gPSAoZG91YmxlKXJlbWFpbmluZ19jYXBhY2l0eSAvIGl0ZW1zW2ldLndlaWdodDsKICAgICAgICAgICAgZG91YmxlIGZyYWN0aW9uYWxfdmFsdWUgPSBmcmFjdGlvbiAqIGl0ZW1zW2ldLnZhbHVlOwogICAgICAgICAgICAKICAgICAgICAgICAgdG90YWxfdmFsdWUgKz0gZnJhY3Rpb25hbF92YWx1ZTsKICAgICAgICAgICAgY3VycmVudF93ZWlnaHQgPSBjYXBhY2l0eTsgLy8gS25hcHNhY2sgbWVuamFkaSBwZW51aAoKICAgICAgICAgICAgcHJpbnRmKCJNZW5nYW1iaWwgSXRlbSAlZCAoQm9ib3QgJWQsIE5pbGFpICVkLCBSYXNpbyAlLjJmKSBkZW5nYW4gRlJBS1NJOiAlLjJmJSUuXG4iLCAKICAgICAgICAgICAgICAgICAgIGl0ZW1zW2ldLmlkLCBpdGVtc1tpXS53ZWlnaHQsIGl0ZW1zW2ldLnZhbHVlLCBpdGVtc1tpXS5yYXRpbywgZnJhY3Rpb24gKiAxMDApOwogICAgICAgICAgICAKICAgICAgICAgICAgYnJlYWs7IC8vIEtuYXBzYWNrIHN1ZGFoIHBlbnVoCiAgICAgICAgfQogICAgfQoKICAgIHJldHVybiB0b3RhbF92YWx1ZTsKfQoKLy8gLS0tIEZ1bmdzaSB1dGFtYSB1bnR1ayBwZW5ndWppYW4gLS0tCmludCBtYWluKCkgewogICAgcHJpbnRmKCI9PT0gVWppIENvYmEgUmF0aW9uYWwgS25hcHNhY2sgKEJhaGFzYSBDKSA9PT1cbiIpOwoKICAgIC8vIERhdGEgVWppCiAgICBJdGVtIGl0ZW1zW10gPSB7CiAgICAgICAgezEsIDIsIDEwLCAwLjB9LCAvLyBSYXNpbyA1LjAKICAgICAgICB7MiwgNCwgMTAsIDAuMH0sIC8vIFJhc2lvIDIuNQogICAgICAgIHszLCA2LCAxMiwgMC4wfSwgLy8gUmFzaW8gMi4wCiAgICAgICAgezQsIDksIDE4LCAwLjB9ICAvLyBSYXNpbyAyLjAKICAgIH07CiAgICBpbnQgbiA9IHNpemVvZihpdGVtcykgLyBzaXplb2YoaXRlbXNbMF0pOwogICAgaW50IGNhcGFjaXR5ID0gMTU7CgogICAgcHJpbnRmKCJLYXBhc2l0YXMgS25hcHNhY2s6ICVkIGtnXG4iLCBjYXBhY2l0eSk7CiAgICBwcmludGYoIkRhZnRhciBJdGVtIEF3YWw6XG5JRCB8IEJvYm90IHwgTmlsYWlcbiIpOwogICAgcHJpbnRmKCItLS18LS0tLS0tLXwtLS0tLS0tXG4iKTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CiAgICAgICAgcHJpbnRmKCIlLTJkIHwgJS01ZCB8ICUtNWRcbiIsIGl0ZW1zW2ldLmlkLCBpdGVtc1tpXS53ZWlnaHQsIGl0ZW1zW2ldLnZhbHVlKTsKICAgIH0KICAgIAogICAgLy8gUGFuZ2dpbCBmdW5nc2kgc29sdXNpCiAgICBkb3VibGUgcmVzdWx0ID0gcmF0aW9uYWxfa25hcHNhY2tfZ3JlZWR5KGl0ZW1zLCBuLCBjYXBhY2l0eSk7CiAgICAKICAgIC8vIFRhbXBpbGthbiBoYXNpbCBkZW5nYW4gMiBhbmdrYSBkaSBiZWxha2FuZyBrb21hCiAgICBwcmludGYoIlxuLS0tIEhhc2lsIEFraGlyIC0tLVxuIik7CiAgICBwcmludGYoIk5pbGFpIE1ha3NpbXVtIE9wdGltYWw6ICQlLjJmXG4iLCByZXN1bHQpOwogICAgcHJpbnRmKCI9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iKTsKCiAgICByZXR1cm4gMDsKfQ==