#include <stdio.h>
#include <stdlib.h>
 
// Struktur untuk merepresentasikan setiap barang
typedef struct {
    int id;           // Nomor identitas barang
    float bobot;      // Bobot barang
    float nilai;      // Nilai barang
    float rasio;      // Rasio Nilai/Bobot (nilai/bobot)
} Barang;
 
// Fungsi perbandingan untuk qsort. Mengurutkan barang berdasarkan Rasio secara MENURUN.
int bandingkan_barang(const void *a, const void *b) {
    Barang *barang_a = (Barang *)a;
    Barang *barang_b = (Barang *)b;
 
    // Logika pengurutan menurun: jika rasio A < rasio B, A harus diletakkan setelah B (return 1).
    if (barang_a->rasio < barang_b->rasio) {
        return 1;
    } else if (barang_a->rasio > barang_b->rasio) {
        return -1;
    } else {
        return 0;
    }
}
 
// Fungsi utama untuk menyelesaikan masalah Rational Knapsack
float knapsack_rational(Barang barang[], int jumlah_barang, float kapasitas_maks) {
    // 1. Urutkan barang berdasarkan rasio Nilai/Bobot secara menurun (Strategi Greedy)
    qsort(barang
, jumlah_barang
, sizeof(Barang
), bandingkan_barang
);  
    float total_nilai = 0.0;
    float sisa_kapasitas = kapasitas_maks;
 
    printf("--- Proses Pengambilan Barang Berdasarkan Rasio (Greedy) ---\n");     printf("| No. | Bobot | Nilai | Rasio | Sisa Kps | Aksi |\n");     printf("----------------------------------------------------------\n");  
    // 2. Proses pengambilan barang
    for (int i = 0; i < jumlah_barang; i++) {
        if (sisa_kapasitas <= 0) {
            break; // Ransel penuh, hentikan iterasi
        }
 
        printf("| %-3d | %-5.1f | %-5.1f | %-5.2f | %-8.2f | ",                 barang[i].id, barang[i].bobot, barang[i].nilai, barang[i].rasio, sisa_kapasitas);
 
        if (barang[i].bobot <= sisa_kapasitas) {
            // Ambil seluruh barang
            total_nilai += barang[i].nilai;
            sisa_kapasitas -= barang[i].bobot;
            printf("Ambil SELURUH (Nilai +%.2f) |\n", barang
[i
].
nilai);         } else {
            // Ambil sebagian (fraksi) barang
            float fraksi = sisa_kapasitas / barang[i].bobot;
            float nilai_diambil = fraksi * barang[i].nilai;
 
            total_nilai += nilai_diambil;
            sisa_kapasitas = 0; // Ransel terisi penuh oleh fraksi ini
            printf("Ambil FRAKSI (%.2f) (Nilai +%.2f) |\n", fraksi
, nilai_diambil
);         }
    }
    printf("----------------------------------------------------------\n");  
    return total_nilai;
}
 
int main() {
    // --- KASUS UJI (Contoh data, GANTI dengan data dari buku Anda) ---
    // Barang-barang dengan Bobot (kg) dan Nilai (Rp)
    float Bobot[] = {10.0, 20.0, 30.0};
    float Nilai[] = {60.0, 100.0, 120.0};
    float KAPASITAS_RANSEL = 50.0; 
 
    int JUMLAH_BARANG = sizeof(Bobot) / sizeof(Bobot[0]);
 
    // Inisialisasi dan pengisian data ke dalam array struktur Barang
    Barang daftar_barang[JUMLAH_BARANG];
    for (int i = 0; i < JUMLAH_BARANG; i++) {
        daftar_barang[i].id = i + 1;
        daftar_barang[i].bobot = Bobot[i];
        daftar_barang[i].nilai = Nilai[i];
        daftar_barang[i].rasio = Nilai[i] / Bobot[i];
    }
 
    printf("--- Rasional Knapsack Problem (Informatika Kelas 11) ---\n");     printf("Kapasitas Ransel: %.2f kg\n\n", KAPASITAS_RANSEL
);  
    // Panggil fungsi utama Knapsack
    float hasil_optimal = knapsack_rational(daftar_barang, JUMLAH_BARANG, KAPASITAS_RANSEL);
 
    printf("\n=============================================\n");     printf("NILAI TOTAL OPTIMAL yang dapat dicapai: Rp%.2f\n", hasil_optimal
);     printf("=============================================\n");  
    return 0;
}