#include<stdio.h>
#include<stdlib.h>
typedef struct gutui{
int g;
int h;
}gutui;
void citire(FILE *f,gutui *a,int n){ //citire vector de structuri din fisier
int i;
int aux;
for(i=0;i<n;i++){
fscanf(f,"%d",&a[i].h); //inaltime
fscanf(f,"%d",&a[i].g); //greutate
}
}
int comparare(const void *a,const void *b){ //functia de comparare folosita pentru sortarea descrescatoare a vectorului de structuri in ordinea inaltimilor
gutui *a1,*b1;
a1=(gutui*)a;
b1=(gutui*)b;
return (*b1).h-(*a1).h;
}
float minim(gutui *v,int n,int *gr,int *poz){ //returneaza minimul din vector
int i;
float min=(float)v[0].g/v[0].h;
for(i=0;i<n;i++){
if( ( (float)v[i].g/v[i].h ) < min){
min=(float)v[i].g/v[i].h;
(*poz)=i; //pozitia elementului minim
(*gr)=v[i].g; //greutatea elementului minim
}
}
return min;
}
int nivel(int h,int hmax,int u){
if(h <= hmax) return h/u; //daca inaltimea nu depaseste inaltimea maxima, intoarce nivelul
return -1; //altfel, intoarce -1 (depasire)
}
int greutate(gutui *v,int n,int hmax,int u){ //parcurge vectorul ordonat (dupa inaltimi) de structuri v pentru a gasi greutatea maxima
gutui *r=(gutui*)calloc(n,sizeof(gutui)); //vector care pastreaza structurile cu valorile cele mai bune pentru raportul greutate/inaltime. Indexul j arata la ce pas a fost adaugat elementul
int i,j=0;
int gr=0;
int poz=0;
int gmax = v[0].g;
int nc=nivel(v[0].h,hmax,u); //nivelul cel mai de sus
r[0]=v[0]; //adauga primul element in vector
i=1;
j=1;
while(i < n) { //pentru fiecare gutuie
while( nivel((v[i].h+j*u),hmax,u) == nc){ //adauga in vector gutuile accesibile de pe nivelul curent
r[j].g=v[i].g;
r[j].h=(v[i].h+j*u); //la pasul j, inaltimea tuturor gutuilor este cu j*u mai mare decat cea initiala
gmax += v[i].g;
i++;
j++;
}
if(i>=n) break;
if(nivel((v[i].h+j*u),hmax,u)!=-1) { //nu exista gutui care sa fi devenit inaccesibile pe nivelul analizat, treci la nivelul urmator ( h nu a devenit mai mare decat hmax )
nc=nivel((v[i].h+j*u),hmax,u);
}
else{
while(nivel((v[i].h+j*u),hmax,u) == -1){ //restul de gutui de pe nivel au devenit inaccesibile (h > hmax), dar pot fi o alegere mai buna
if(i>=n) break;
if( (float)v[i].g/ (v[i].h+j*u) > minim(r,j,&gr,&poz) ) { //elementul curent este mai bun decat cel mai prost element din vector
//il aleg in locul minimului (deci cu inaltimea corespunzatoare pasului poz )
gmax -= gr;
gmax += v[i].g;
r[poz].g= v[i].g;
r[poz].h=(v[i].h+poz*u); //inlocuieste si in vector minimul cu noua valoare
j++;
}//if
i++;
}//while
}//else
}//while
return gmax;
}
int main(){
gutui *v;
int gmax;
int aux,hmax,u;
int n;
FILE *f,*g;
f=fopen("gutui.in","rt");
g=fopen("gutui.out","wt");
fscanf(f,"%d",&n); //citire numar gutui
fscanf(f,"%d",&hmax); //citire inaltime maxima
fscanf(f,"%d",&u); //citire inaltime cu care se ridica crengile la fiecare gutuie culeasa;
v=(gutui*)malloc(n*sizeof(gutui)); //alocare memorie pentru vectorul de structuri
citire(f,v,n); //citire perechi gutuie-inaltime din fisier
qsort(v,n,sizeof(gutui),comparare);
gmax=greutate(v,n,hmax,u);
fprintf(g,"%d",gmax);
fclose(f);
fclose(g);
}