Cod sursa(job #436847)

Utilizator dragos.denaDena Dragos dragos.dena Data 9 aprilie 2010 00:04:25
Problema Gutui Scor 0
Compilator c Status done
Runda teme_upb Marime 4.03 kb
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
//#define DEBUG

#define INITIAL_ALLOCED 10
#define INDEX(h)  ((H - (h))/U) 		// nivelul in care intra o anumita gutaie in functie de inaltime
#define LEVELS    ((H/U) + 1)			// numarul de nivele in functie de intalimea maxima si diferenta dintre 
										// nivele

typedef struct _gt		// descrie o gutuie prin g (greutate) si h (inaltime)
{
	uint32_t g;
	uint32_t h;
} Gut, *PGut;

typedef struct _level	// descrie un nivel -- o sectiune care cuprinde gutuile intre o inaltime h si h + U 
						// (unde h - 1 este divizibil cu U)
{
	uint32_t size;					// numarul de gutui din nivelul curent
	uint32_t alloced;				// numarul de PGut alocate
	int32_t current_primary_max;	// index-ul din entries cu gutuia cu greutatea cea mai mare (sau -1)
	int32_t current_secondary_max;	// index-ul din entries cu gutuia cu a doua greutate (sau -1)
	PGut* entries;					// size intrari de tipul PGut care descriu gutuile din nivelul curent
} Level, *PLevel;

int N, H, U;		// Numarul de Gutui, Inaltimea maxima, Pasul de inaltare

PLevel   level_new();							// Aloca memorie pentru un nou nivel
void     level_append(PLevel, PGut);			// Adauga o intrare de tip PGut intr-un nivel
uint32_t level_get_primary_max_g(PLevel);		// Returneaza greutatea maxima dintr-un nivel
uint32_t level_get_secondary_max_g(PLevel);		// Returneaza a doua greutate dintr-un nivel
uint32_t level_remove_primary_max(PLevel);		// Sterge elementul cu cea mai mare greutate (si o returneaza)
uint32_t level_remove_secondary_max(PLevel); 	// Sterge elementul cu a doua greutate (si o returneaza)
void	 level_sort(PLevel);					// Sorteza intrarile dintr-un anumit nivel dupa greutate

int main()
{
	freopen("gutui.in", "r", stdin);
	freopen("gutui.out", "w", stdout);
	int i, j;
	scanf("%d%d%d", &N, &H, &U);
	PLevel* levels = (PLevel*)calloc(LEVELS, sizeof(PLevel));
	for(i = 0; i < LEVELS; i ++)
		levels[i] = level_new();
	for(i = 0; i < N; i ++)
	{
		PGut gut = (PGut)malloc(sizeof(Gut));
		scanf("%d%d", &gut->h, &gut->g);
		level_append(levels[INDEX(gut->h)], gut);
	}
	for(i = 0; i < N; i ++)
		level_sort(levels[i]);
#ifdef DEBUG	
	for(i = 0; i < LEVELS; i ++)
	{
		printf("Nivelul %d\n", i);
		for(j = 0; j < levels[i]->size; j ++)
			printf("(%d %d) ", levels[i]->entries[j]->g, levels[i]->entries[j]->h);
		printf("\n\n");
	}
#endif

	return 0;
}

PLevel   level_new()
{
	PLevel level = (PLevel)malloc(sizeof(Level));
	level->size = 0;
	level->alloced = INITIAL_ALLOCED;
	level->current_primary_max = -1;
	level->current_secondary_max = -1;
	level->entries = (PGut*)malloc(INITIAL_ALLOCED * sizeof(PGut));
	level->entries[0] = NULL;
	return level;
}

void     level_append(PLevel lvl, PGut gut)
{
	if(lvl->size == lvl->alloced - 1)
	{
		lvl->alloced *= 2;
		lvl->entries = (PGut*)realloc(lvl->entries, lvl->alloced * sizeof(PGut));
	}
	lvl->entries[lvl->size ++] = gut;
	lvl->entries[lvl->size] = NULL;
}

uint32_t level_get_primary_max_g(PLevel lvl)
{
	if(lvl->current_primary_max == -1)
		return 0;
	else
		return lvl->entries[lvl->current_primary_max]->g;
}

uint32_t level_get_secondary_max_g(PLevel lvl)
{
	if(lvl->current_secondary_max == -1)
		return 0;
	else
		return lvl->entries[lvl->current_secondary_max]->g;
}

uint32_t level_remove_primary_max(PLevel lvl)
{
	if(lvl->current_primary_max == -1)
		return 0;
	uint32_t ret = lvl->entries[lvl->current_primary_max]->g;
	lvl->current_primary_max = lvl->current_secondary_max;
	lvl->current_secondary_max ++;
	if(lvl->current_secondary_max == 0 || lvl->entries[lvl->current_secondary_max] == NULL)
		lvl->current_secondary_max = -1;
	return ret;
}

uint32_t level_remove_secondary_max(PLevel lvl)
{
	if(lvl->current_secondary_max == -1)
		return 0;
	uint32_t ret = lvl->entries[lvl->current_secondary_max]->g;
	lvl->current_secondary_max ++;
	if(lvl->entries[lvl->current_secondary_max] == NULL)
		lvl->current_secondary_max = -1;
	return ret;
}

int comp_gut(const void* gut1, const void* gut2)
{
	return (*(PGut*)gut1)->g - (*(PGut*)gut2)->g;
}

void level_sort(PLevel lvl)
{
	qsort(lvl->entries, lvl->size, sizeof(PGut), comp_gut);
}