Cod sursa(job #440874)

Utilizator chocapicSima Ana chocapic Data 12 aprilie 2010 17:03:58
Problema Gutui Scor 10
Compilator c Status done
Runda teme_upb Marime 3.94 kb
#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);
}