Cod sursa(job #437009)

Utilizator valentin.gosuGosu Valentin valentin.gosu Data 9 aprilie 2010 03:58:31
Problema Gutui Scor 60
Compilator c Status done
Runda teme_upb Marime 5.05 kb
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>


typedef void *T;

struct heap_s {
    int size;
    int capacity;
    T *data;
};

typedef struct heap_s *Heap;

/*
 * Functia H_New creaza un heap nou cu capacitatea 'max'
 *  aloca memorie pentru el, si returneaza adresa lui
 */
Heap H_New(int max)
{
    Heap heap;
    assert(max > 0);
    heap = (struct heap_s *) malloc(sizeof(struct heap_s));
    heap->size = 0;
    heap->capacity = max;
    heap->data = (T*)malloc((heap->capacity) * sizeof(T));
    return heap;
}

/*
 * Functia elibereaza memoria folosita de heap.
 */
void H_Delete(Heap heap)
{
    assert(heap);
    heap->capacity = 0;
    heap->size = 0;
    if (heap->data) /* este posibil ca vectorul sa nu fie alocat */
        free(heap->data); 
    free(heap);
}

/* Returneaza 1 daca heapul este gol si 0 daca contine elemente */
int H_Empty(Heap heap)
{
    assert(heap);
    return heap->size == 0;
}

/* Returneaza 1 daca heapul a atins capacitatea maxima */
int H_Full(Heap heap)
{
    assert(heap);
    return heap->size == heap->capacity;
}

/* Returneaza primul element din heap */
T H_FindMin(Heap heap)
{
    assert(heap);
    assert(heap->size > 0);
    return heap->data[0];
}

static void H_Down(Heap h, int p, int (*compare) (T x, T y));
static void H_Up(Heap h, int p, int (*compare) (T x, T y));

/* Sterge primul element din heap si actualizeaza heapul */
void H_RemoveMin(Heap heap, int compare(T x, T y))
{
    T x;
    assert(heap);
    assert(heap->size > 0);
    assert(compare);
    x = heap->data[0];
    heap->data[0] = heap->data[--heap->size];
    H_Down(heap, 0, compare);
}

void H_Insert(Heap * heap, T key, int compare(T x, T y))
{
    int i, capacity;
    assert(heap);
    assert(*heap);
    assert((*heap)->size >= 0);
    if ((*heap)->size == (*heap)->capacity) {

        T *data;
        capacity = (*heap)->capacity;
        data = (*heap)->data;
        (*heap)->data = NULL;
        H_Delete(*heap);
        *heap = H_New(capacity*2);
        (*heap)->size = capacity;
        for (i = 0; i < (*heap)->size; i++)
            (*heap)->data[i] = data[i];
        assert(data);
        free(data);

    }
    (*heap)->data[(*heap)->size++] = key;
    H_Up(*heap, (*heap)->size - 1, compare);
}

/* Returneaza numarul de elemente din heap */
int H_Size(Heap heap)
{
    assert(heap);
    return heap->size;
}

/* Returneaza capacitatea heapului */
int H_Capacity(Heap heap)
{
    assert(heap);
    return heap->capacity;
}

/* Functia Coboara elementul din pozitia p si actualizeaza heapul */
static void H_Down(Heap h, int p, int (*compare) (T x, T y))
{
    int fiu;
    T t;
    while (2 * p + 1 < h->size) {
        fiu = 2 * p + 1;
        if (fiu + 1 < h->size && compare(h->data[fiu], h->data[fiu
                                                               + 1]) > 0) {
            fiu++;
        }
        if (compare(h->data[fiu], h->data[p]) < 0) {
            t = h->data[p];
            h->data[p] = h->data[fiu];
            h->data[fiu] = t;
            p = fiu;
        } else {
            break;
        }
    }
}

/* Functia Urca elementul din pozitia p si actualizeaza heapul */
static void H_Up(Heap h, int p, int (*compare) (T x, T y))
{
    T aux;

    if (p == 0)
        return;

    while (p > 0
           && (compare(h->data[p], h->data[(p - 1) / 2]) <
               0)) {
        aux = h->data[p];
        h->data[p] = h->data[(p - 1) / 2];
        h->data[(p - 1) / 2] = aux;

        p = (p - 1) / 2;
    }
}

 
 int N,H,U; 
 
 typedef struct {
 	int h;
 	int g;
 	} gutuie;
 
 int comp(T a, T b) {
 	return *(int*)a - *(int*)b;
 	}
  
 int main() {
 	FILE * f;
 	FILE * g;
 	f=fopen( "gutui.in","r");
 	g=fopen("gutui.out","w");

 	fscanf(f,"%d %d %d",&N,&H,&U);
 	int i,j;
 	gutuie v[N];
 	for (i=0;i<N;i++) {
 		int a,b;
 		fscanf(f,"%d %d",&a,&b);
 		if (a<=H) {
 			v[i].h=a;
 			v[i].g=b;
 		} else {
 			N--;
 			i--;
 			continue;
 			}
 		}
 	
 	
 	for (i=0;i<N;i++)
 		for (j=i+1;j<N;j++) {
 			if ((H-v[i].h)/U > (H-v[j].h)/U) {
 				gutuie aux=v[i];
 				v[i]=v[j];
 				v[j]=aux;
 				}
 			if ( (H-v[i].h)/U == (H-v[j].h)/U && v[i].g < v[j].g) {
 				gutuie aux=v[i];
 				v[i]=v[j];
 				v[j]=aux;
 				}
 			}
 	
 	
 	for (i=0;i<N;i++)
 		;//printf("%d %d\n",v[i].h,v[i].g);
 	
 	
 	Heap heap = H_New(N);
 	for (i=0;i<N;i++) 
 		;//H_Insert(&heap,&v[i].g,comp);
 		
 	
 	int niv=(H-v[0].h)/U; int count=niv;
 	for (i=0;i<N;i++) 
 		if ( (H-v[i].h)/U == niv ) {
 			if ( H_Size(heap) < niv+1 ) {
 				H_Insert(&heap,&v[i].g,comp);
 				count--;
 				continue;
 				}
 			if ( H_Size(heap)==niv+1 && count>=0)
 				if (*(int*)H_FindMin(heap)<v[i].g) {
 					H_RemoveMin(heap,comp);
 					H_Insert(&heap,&v[i].g,comp);
 					count--;
 					continue;
 					}
 			if (count<0) {
 				niv++;
 				count=niv;
 				}
 			} else if ( (H-v[i].h)/U > niv ) {
 				niv = (H-v[i].h)/U;
 				count=niv;
 				i--;
 				continue;
 				}
 	int suma=0;			 				
 	while ( H_Size(heap)>0) {
 		printf("%d ",*((int*)H_FindMin(heap)));
 		suma+=*((int*)H_FindMin(heap));
 		H_RemoveMin(heap,comp);
 		}
 	printf("\n");
 	fprintf(g,"%d\n",suma);
 	fclose(g);
 	return 0;
 	}