Cod sursa(job #436464)

Utilizator MEmmaMirica Emma MEmma Data 8 aprilie 2010 16:39:09
Problema Gutui Scor 10
Compilator c Status done
Runda teme_upb Marime 4.08 kb
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct H{
     int *val;
     int dim;
     } Heap;
     
int min(int a, int b)
{
    return (a < b) ? a : b;
}

void swap(int a[], int i, int j)
{
    int aux;
    aux = a[i];
    a[i] = a[j];
    a[j] = aux;
}

Heap* CreateHeap(int n, int dimHeap)
{
    Heap *h = (Heap*)malloc(sizeof(Heap));
    h->dim = dimHeap;
    h->val = (int*)malloc(n*sizeof(int));
    return h;
}

int Parinte(Heap *h, int poz){
	if ((poz-1)/2 < h->dim)
		return (poz-1)/2;
	else return -1;
	} 
	
int DescS(Heap *h, int poz){
	if ( 2*poz+1 < h->dim)
		return 2*poz+1;
	else
		return -1;
	}

int DescD(Heap *h, int poz){
	if ( 2*poz+2 < h->dim )
		return 2*poz+2;
	else
		return -1;
	}

void UrcaValoare(Heap *h, int poz){
	 while (poz > 0 && h->val[poz] < h->val[Parinte(h,poz)] ){
		swap(h->val,poz,Parinte(h,poz));
		poz = Parinte(h,poz);
		}
	}      
	
void CoboaraValoare(Heap *h, int poz){
	int pozDesc;
	for (;;){
		if ( 0 > poz || poz > h->dim || 0 > 2*poz +1 || 2*poz+2 > h->dim || 0 > 2*poz+2 || 2*poz+2 > h->dim )
			return;
		if (h->val[poz] < h->val[DescS(h,poz)] && h->val[poz] < h->val[DescD(h,poz)] )
			return;
		if (h->val[DescS(h,poz)] < h->val[poz] && h->val[DescS(h,poz)] < h->val[DescD(h,poz)] )
			pozDesc = DescS(h,poz);
		else 
			pozDesc = DescD(h,poz);
	     swap(h->val,poz,pozDesc);
		}
}

void AdaugaValoare(Heap *h, int val){
	h->dim++;
	h->val[h->dim-1] =  val;
	UrcaValoare(h,h->dim-1);
	}
	
int ExtrageMinim(Heap *h){
	int min = h->val[0];
	swap(h->val,0,h->dim);
	h->dim--;
	CoboaraValoare(h,0);
	return min;
	}
	
int Minim(Heap *h)
{
     return h->val[0];
}
    
void merge(int *h, int *w, int p, int q, int r, int H, int U)
{
    int i = p;
    int j = q + 1;

    int *tmp = (int *) malloc((r - p + 1) * sizeof(int));
    int *tmp2 = (int *) malloc((r - p + 1) * sizeof(int));
    int k = 0;

    while ((i <= q) && (j <= r)) {
        if (((H - h[i]) / U < (H - h[j]) / U)
            || ((H - h[i]) / U == (H - h[j]) / U && (w[i] > w[j]))) {
            tmp2[k] = w[i];
            tmp[k++] = h[i++];
        } else {
            tmp2[k] = w[j];
            tmp[k++] = h[j++];
        }
    }

    while (i <= q) {
        tmp2[k] = w[i];
        tmp[k++] = h[i++];
    }

    while (j <= r) {
        tmp2[k] = w[j];
        tmp[k++] = h[j++];
    }

    memcpy(h + p, tmp, (r - p + 1) * sizeof(int));
    memcpy(w + p, tmp2, (r - p + 1) * sizeof(int));
    free(tmp);
    free(tmp2);
}

void mergeSort(int *h, int *w, int p, int r, int H, int U)
{
    if (p < r) {
        int q = (p + r) / 2;
        mergeSort(h, w, p, q, H, U);
        mergeSort(h, w, q + 1, r, H, U);
        merge(h, w, p, q, r, H, U);
    }
}


int main()
{
    int N, H, U;
    FILE *f, *g;
    f = fopen("gutui.in", "r");
    g = fopen("gutui.out", "w");
    fscanf(f, "%d%d%d", &N, &H, &U);
    int h[N], w[N], hh, ww;
    int i;
    int n = 0;
    
    // adaugam doar gutuile care initial se afla la o inaltime mai mica sau egala cu H
    for (i = 0; i < N; i++) {
        fscanf(f, "%d %d\n", &hh, &ww);
        if (hh <= H) {
            w[n] = ww;
            h[n++] = hh;
        }
    }

    // sortam in O(n*log(n)) crescator dupa nivel si apoi pentru niveluri egale descrescator dupa greutati   
    mergeSort(h, w, 0, n - 1, H, U);
    
    Heap *aux;
    aux = CreateHeap(n,0);
    int p;
     int j = 0;
    int nivel = (H-h[0])/U; p = nivel+1;
    for (i = 0; i < n; i++) {
       if (nivel == (H - h[i])/U){
          if (j<=nivel){
               if (aux->dim < nivel+1 )
                    AdaugaValoare(aux,w[i]);
               else 
                    if (Minim(aux) < w[i] ){
                         ExtrageMinim(aux);
                         AdaugaValoare(aux,w[i]);
                    }
               j++;
         }
         else continue;
     }else {
            nivel = (H-h[i])/U;
            j = 0;
            i--;
            }}
    printf("\n");
    int Gmax = 0;
    p = aux->dim;
    for ( i = 0; i< aux->dim; i++){
     printf("%d ",aux->val[i]);
     Gmax+=aux->val[i];
    }
    printf("\n");
    fprintf(g, "%d\n", Gmax);
    fclose(f);
    fclose(g);
    return 0;
}