/*
Gigel are in curte un gutui. El se hotaraste sa culeaga cat mai multe gutui, dar are o problema: copacul este atat de incarcat
* cu fructe incat la fiecare gutuie culeasa, toate crengile acestuia se ridica in inaltime cu fix U centimetrii. Din pacate Gigel
* nu are scara la el si nu poate sa culeaga gutui la o inaltime mai mare de H centimetrii.
Nici de aceasta data Gigel nu se descurca singur. Ajutati-l sa culeaga cat mai multe gutui.
Stiind greutatea si inaltimea initiala a fiecarui fruct, se cere cea mai mare recolta de gutui pe care o poate aduce Gigel acasa.
* Cum se gandeste sa le vanda in piata, il intereseaza o greutate cat mai mare, nu un numar cat mai mare.
Date de intrare
Pe prima linie a fisierului de intrare gutui.in se afla 3 numere intregi: N (numarul de gutui din copac), H (inaltimea maxima la
* care ajunge Gigel) si U (cu cat se ridica crengile copacului dupa culegerea unei gutui).
Pe urmatoarele N linii se afla cate 2 numere intregi reprezentand inaltimiile si greutatile gutuilor din copac.
Date de ieşire
In fisierul de iesire gutui.out trebuie scrisa greutatea maxima a gutuilor pe care le poate culege Gigel.
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
//structura ce caracterizeaza un gutui
struct gutui
{
long int inaltime;
long int greutate;
};
typedef struct gutui Gutui;
//structura cu gutui si prioritate pe care o are in anumite circumstante
struct date
{
Gutui fruct;
long int priority;
};
typedef struct date date_t;
struct heap
{ long n;//nr de elem
date_t * a;//un vector a
};
typedef struct heap* HB;
//nu am folosit librarii ca sa pot sort dar am luat algoritmul de pe net
void quicksort(date_t * arr, long int low, long int high) {
long int i = low;
long int j = high;
date_t y ;
/* compare value */
date_t z = arr[(low + high) / 2];
/* partition */
do {
/* find member above ... */
while(arr[i].priority > z.priority) i++;
/* find element below ... */
while(arr[j].priority < z.priority) j--;
if(i <= j) {
/* swap two elements */
y = arr[i];
arr[i] = arr[j];
arr[j] = y;
i++;
j--;
}
} while(i <= j);
/* recurse */
if(low < j)
quicksort(arr, low, j);
if(i < high)
quicksort(arr, i, high);
}
//Constructorul cozii de tip Heap
HB NewHeap(int maxim)
{
HB h=(HB)malloc(sizeof(struct heap));
h->n=0;
h->a=(date_t*)malloc(maxim*sizeof(struct date_t*));
return h;
}
//Verifica daca coada este goala sau nu
int EmptyHB(HB h)
{
return h->n==0;
}
date_t get_min(HB h)
{
return h->a[0];
}
//Sterge elementul cu costul cel mai mic din coada prioritara si il intoarce
void Replace(HB h,date_t x)
{
assert(!EmptyHB(h));
date_t aux=h->a[0];
h->a[0]=x;
//h->n--;
}
//Insereaza element in heap
void InsertHB(HB h,date_t x0)
{
h->n++;
int n=h->n;
h->a[n-1]=x0;
}
//Reconstruieste structura de tip Heap, in functie de formula de cost
void rebuildHeap(date_t *a, int heapDim, int i)
{
int left, right, max;
date_t temp;
left = 2*i+1;
right = 2*i+2 ;
if ((left<heapDim) && (a[left].priority<a[i].priority)) max = left;
else max = i;
if ((right<heapDim) && (a[right].priority<a[max].priority)) max = right;
if (max!=i)
{
temp = a[i];a[i] = a[max];a[max] = temp;
rebuildHeap(a, heapDim, max);
}
}
//Construieste un heap
void buildHeap(HB h)
{
int i;
for(i=h->n/2-1; i>=0; i--)
rebuildHeap(h->a,h->n, i);
}
int det_min(date_t *vec,long int n)
{
long int i,j=0,min=vec[0].priority;
for(i=0;i<n;i++)
if(min>vec[i].priority)
{
min=vec[i].priority;
j=i;
}
return j;
}
int main()
{
FILE *pf_int,*pf_ies;
long int j=0,n_cules=0,i = 0 , N = 0 , kg=0, H = 0 , U = 0 ;
date_t *copac,data;//copac=toate gutuiele din copac, cules= gutuile culese de Gigel
pf_int = fopen("gutui.in","r");
HB cules;
pf_ies = fopen("gutui.out","w");
fscanf(pf_int,"%ld %ld %ld",&N,&H,&U);
copac=(date_t*)malloc((N+1)*sizeof(date_t));
//citesc toate fructele
for( i = 0; i < N ; i++ )
{
fscanf(pf_int,"%ld %ld",&copac[i].fruct.inaltime,&copac[i].fruct.greutate);
copac[i].priority=copac[i].fruct.inaltime;//prioritatea cu care sunt in copac e inaltimea
}
//le sortez descrescator in functie de inaltime
quicksort(copac,0,N-1);
i=0;
cules=NewHeap(N);
//cat timp nu am parcurs toate gutuiele din copac
while(i<N)
{
if(cules->n*U+copac[i].fruct.inaltime<=H)//vad daca e o gutuie pe care pot sa o ajung la momentul respectiv
{
//daca da o culeg
data.fruct=copac[i].fruct;
data.priority=copac[i].fruct.greutate;
InsertHB(cules,data);
rebuildHeap(cules->a,cules->n,0);
}
else
{
//daca nu atunci verific daca gutuia cea mai usoara din cele culese nu e mai usoara si decat gutuia curenta
//daca da, atunci le interschimb
data=get_min(cules);
if(data.priority<copac[i].fruct.greutate)
{
data.priority=copac[i].fruct.greutate;//priotatea cu care le pun in cos greutatea
data.fruct=copac[i].fruct;
Replace(cules,data);
rebuildHeap(cules->a,cules->n,0);
}
}
i++;
}
//determin greutatea maxima
for(i = 0 ; i<cules->n; i++ )
{
kg+=cules->a[i].priority;
}
fprintf(pf_ies,"%ld\n",kg);
fclose(pf_int);
fclose(pf_ies);
return 0;
}