Cod sursa(job #439418)

Utilizator melania.patruPatru Melania melania.patru Data 11 aprilie 2010 16:05:17
Problema Gutui Scor 10
Compilator c Status done
Runda teme_upb Marime 6.01 kb
/* gutui.c*/

#include <unistd.h> /* pentru open(), exit() */
#include <errno.h> /* perror() */
#include <stdlib.h>
#include <stdio.h>


#define INF 32000
#define MAX(a,b) ((a)>(b) ? (a) : (b))
#define MIN(a,b) ((a)<(b) ? (a) : (b))

void fatal(char * mesaj_eroare)
{
     perror(mesaj_eroare);
     exit(1);
}

typedef struct gutuia {
                int greutate;     
                int inaltime;   
               
} Tgutuie, *Agutuie;

Tgutuie  gutui[100000];
int mergeaux[100000];
int N,H,U;
int n;


static void ReadFile()
{
     FILE *file_in= fopen("gutui.in", "r");
     int copiat;
     /*citim N (numarul de gutui din copac)*/
     if(!file_in) printf("avem o mare problema\n");
   
     copiat=fscanf(file_in, "%i",&N);
     if(!copiat)  fatal("eroare la citire N din fisier"); 
  
     /* H (inaltimea maxima la care ajunge Gigel)*/ 
     
     copiat=fscanf(file_in, "%i",&H);
     if(!copiat)  fatal("eroare la citire H din fisier"); 
   
      /*U  (cu cat se ridica crengile copacului dupa culegerea unei gutui)*/
     copiat=fscanf(file_in, "%i",&U);
     if(!copiat)  fatal("eroare la citire U din fisier"); 
   
     
     int i,g,h;
     int j=0;
     for(i=0;i<N;i++){
     
            copiat=fscanf(file_in, "%i",&h);
            if(!copiat)  fatal("eroare la citire inaltime din fisier");
            copiat=fscanf(file_in, "%i",&g);
            if(!copiat)  fatal("eroare la citire greutate din fisier");
            if((H-h)/U+1>0)
            {
            gutui[j].inaltime=(H-h)/U+1;
            gutui[j].greutate=g;
            j++;
            }
                                  
     }
     n=j;
     fclose(file_in);
       
}



int compare_by_height_and_weight (const void * a, const void * b)
{
  if(((Tgutuie *)b)->inaltime == ((Tgutuie *)a)->inaltime)
  return ( ((Tgutuie *)b)->greutate - ((Tgutuie *)a)->greutate );
  return ( ((Tgutuie *)b)->inaltime - ((Tgutuie *)a)->inaltime );
}
/*static void AfisareGutui(Agutuie g, int n)

{

int i=0;
printf("\n------\n");
while(i<n){

printf("%i %i\n",g->inaltime,g->greutate);

g++;

i++;

}
printf("\n------\n");
}

static void Afisare(int* g, int n)

{

int i=0;
printf("\n------\n");
while(i<n){

printf("%i\n",*g);

g++;

i++;

}
printf("\n------\n");
}*/
static int merge (Agutuie p, int lp, Agutuie q,int lq)
{
    int i=0;
    int j=0;
    int k=0;
    Agutuie aux=p;
    while(i<lp&&j<lq&&k<aux->inaltime)
        if (aux->greutate >= q->greutate){
                 mergeaux[k]=aux->greutate;
                 aux++;
                 i++;
                 k++;            
              }
        else{
                 mergeaux[k]=q->greutate;
                 q++;
                 j++;
                 k++;            
              }
    while(i<lp&&k<p->inaltime){
                 mergeaux[k]=aux->greutate;
                 aux++;
                 i++;
                 k++;            
              }
             
    while(j<lq&&k<p->inaltime){
                 mergeaux[k]=q->greutate;
                 q++;
                 j++;
                 k++;            
              }
    
    k= MIN(lp+lq,p->inaltime);
  
    return k;
    
}
static int alegere_gutui(Agutuie gutui)
{
 
 
 qsort (gutui, n, sizeof(Tgutuie), compare_by_height_and_weight);
 //AfisareGutui(gutui,n);
   
 long greutate=0;
 Agutuie p,q,aux;
 int i,k,lp;
 int limita_categorie;
 int diferenta_categorie;
 int inaltimea_categoriep;
 int lungime_catp_utila;
 int lungime_catq_utila;
 //pregatire date pas initial
 p=gutui;
 q=gutui;
 while(q->inaltime==p->inaltime&& q-gutui<n) q++;
 diferenta_categorie=(p->inaltime-q->inaltime);
 while(q-gutui<n){
         
         //fructe ce vor fi culese 
         inaltimea_categoriep=p->inaltime;
         for(i=0;i<MIN(diferenta_categorie,p->inaltime)&&p<q&&q-gutui<n;i++){
             greutate+=p->greutate;
            // printf("%i+",p->greutate);
             p++;
         }
        
         
         
        //pregatirea date pentru pasul urmator
         aux=p;
         while(aux<q && aux-p < q->inaltime) {aux->inaltime=q->inaltime;  aux++;} 
         lungime_catp_utila=aux-p;
         
         //AfisareGutui(gutui,n);
         
         aux=q; 
         while(q->inaltime==p->inaltime&& q-gutui<n&& (q-aux)<p->inaltime) q++;
         lungime_catq_utila=q-aux;
         
        
         qsort (p, q-p, sizeof(Tgutuie), compare_by_height_and_weight);
         //daca au mai ramas fructe din prima categorie cu inalimea p->inaltime
         //interclasam elementele in functie de greutate si modifica inalimea  
         //altfel nu inteclasam si p devine automat urmatoarea categorie
         /*if(p!=aux)  {
                     //printf("dupa sortare:%i %i %i si %i %i %i ",p->inaltime,p->greutate,lungime_catp_utila,aux->inaltime,aux->greutate,lungime_catq_utila);
                     k=merge(p,lungime_catp_utila,aux,lungime_catq_utila);
                    // AfisareGutui(gutui,n);
                        i=0;
                        aux=p;
                        while(i<k){
                           aux->greutate=mergeaux[i];
                           aux++;
                           i++;           
                        }
                      //printf("dupa merger");
                      //Afisare(mergeaux,k);
                      //AfisareGutui(gutui,n);
                     }
                     
         //trecem la urmatoarea categorie*/
         while(q->inaltime==p->inaltime&& q-gutui<n) q++;
        
        
        
         
      
 }
 //culegerea ultimelor fructe
 k=p->inaltime;
 for(i=0;i<k;i++){
             greutate+=p->greutate;
            // printf("%i+",p->greutate);
             p++;
 }

 return greutate; 
 
 
}

int main(void)
{
    ReadFile();
    FILE *file_out= fopen("gutui.out", "w");
    fprintf(file_out,"%i\n",alegere_gutui(gutui));
    fclose(file_out);
    //getchar();
    return 0;
}