Cod sursa(job #438588)

Utilizator TokPhobiaCosoi Andrei TokPhobia Data 10 aprilie 2010 21:28:29
Problema Gutui Scor 0
Compilator c Status done
Runda teme_upb Marime 4.39 kb
#include <stdio.h>
#include <stdlib.h>

#define FILEIN "gutui.in"
#define FILEOUT "gutui.out"
#define DIM 100002

typedef struct gutuie {
	int g, h;
} gutuie;

int min(int a, int b) {
	if (a<b) return a;
	return b;
}

int insert(int** culegeri[DIM], gutuie gut, int h, int u, int n) {
	//puts("intram in insert");
	int pozitie_preferata = n, **pozitie_urmatoare = NULL, *val_pozitie_urmatoare = NULL;
	
	/*int i;
	printf("Tratam gutuia G=%d, H=%d. La inceput: ", gut.g, gut.h);
	for (i=0; i<=n; i++)
		if (culegeri[i] == NULL) printf("nul ");
		else printf("%d ", *(*(culegeri[i])));
	printf("enter\n");*/
	
	//calculam pozitia pe care am vrea sa introducem gutuia
	pozitie_preferata = min((h-gut.h)/u, n);
	
	if (culegeri[pozitie_preferata] != NULL)    //daca incercam sa introducem gutuia pe o pozitie deja ocupata
		pozitie_preferata = *(*(culegeri[pozitie_preferata])); //gasim prima pozitie libera indicata
		
	if (pozitie_preferata < 0) 					//daca nu am putut determina o pozitie pe care sa introducem gutuia
		return 0;
	
	//printf("Prefer pe %d\n", pozitie_preferata);
	
	//in acest moment am gasit pozitia pe care urmeaza sa introducem gutuia
	//acum trebuie sa actualizam pozitiile libere indicate de gutuile inconjuratoare
	
	if (pozitie_preferata == n || culegeri[pozitie_preferata+1] == NULL) { 	//daca nu culegem o gutuie imediat dupa ea
		
		if (pozitie_preferata == 0 || culegeri[pozitie_preferata-1] == NULL) { //daca nu culegem o gutuie imediat inaintea ei
			//printf("a\n");
			/*pozitie_urmatoare = (int*)malloc(sizeof(int)); 				//cream un int in care memoram pozitia urmatoare libera
			*pozitie_urmatoare = pozitie_preferata - 1; 				//memoram in acel int pozitia urmatoare libera
			//setam pe pozitia aleasa in 'culegeri' sa indice catre un pointer care duce la int-ul cu numarul pozitiei libere
			culegeri[pozitie_preferata] = &pozitie_urmatoare;*/
			pozitie_urmatoare = (int**)malloc(sizeof(int*)); 				//cream un int in care memoram pozitia urmatoare libera
			*pozitie_urmatoare = val_pozitie_urmatoare = (int*)malloc(sizeof(int)); //memoram in acel int pozitia urmatoare libera
			*val_pozitie_urmatoare = pozitie_preferata - 1;
			//setam pe pozitia aleasa in 'culegeri' sa indice catre un pointer care duce la int-ul cu numarul pozitiei libere
			culegeri[pozitie_preferata] = pozitie_urmatoare;
			pozitie_urmatoare = val_pozitie_urmatoare = NULL;
		}
		else { //daca avem un element in fata noastra
			//printf("b\n");
			//primul element liber care urmeaza este cel indicat de elementul din fata noastra
			culegeri[pozitie_preferata] = culegeri[pozitie_preferata-1];
		}
	} else { //daca avem un element in spatele nostru
		//daca nu avem un element in fata noastra
		if (pozitie_preferata == 0 || culegeri[pozitie_preferata-1] == NULL) {
			//printf("c\n");
			//elementul liber de dupa noi este cel din fata noastra si impartim adresa la care il memoram cu cel din spatele nostru
			culegeri[pozitie_preferata] = culegeri[pozitie_preferata+1];
			*(*(culegeri[pozitie_preferata])) = *(*(culegeri[pozitie_preferata])) - 1;	
		}
		else { //daca avem un element si in fata noastra (suntem inconjurati)
			//printf("d\n");
			//elementele din spatele nostru, ca si noi, vor indica la pozitia indicata de elementele din fata noastra
			free(*culegeri[pozitie_preferata+1]);
			culegeri[pozitie_preferata+1] = culegeri[pozitie_preferata] = culegeri[pozitie_preferata-1];
		}
	}
	/*
	printf("La sfarsit: ");
	for (i=0; i<=n; i++)
		if (culegeri[i] == NULL) printf("nul ");
		else printf("%d ", *(*(culegeri[i])));
	printf("\n\n");
	*/
	return 1;
}

int comparator(const void * a, const void * b) {
	return -1*(((gutuie*)a)->g - ((gutuie*)b)->g);
}


int main() {
	
	FILE *fin = fopen(FILEIN, "r"), *fout = fopen(FILEOUT, "w");
	int n, h, u, i;
	long int totalsum = 0;						//definim suma totala si intializam cu 0
	gutuie gutui[DIM];							//definim vectorul de gutui
	int** culegeri[DIM];
	
	//citim datele intr-o lista de gutui
	fscanf(fin, "%d %d %d", &n, &h, &u);
	
	for (i=0; i<n; i++) {
		fscanf(fin, "%d %d", &gutui[i].h, &gutui[i].g);
		culegeri[i] = NULL;
	}
	culegeri[n] = NULL;
	//sfarsit citit date
	
	//sortam datele
	qsort(gutui, n, sizeof(gutuie), comparator);
	
	for (i=0; i<n; i++)
		//vedem daca putem culege gutuia si ne marcam in vector
		if (insert(culegeri, gutui[i], h, u, n))
			totalsum += gutui[i].g;
	
	//printf("\nRezultat final: %ld\n", totalsum);
	fprintf(fout, "%ld\n", totalsum);
	
	fclose(fin);
	fclose(fout);
	
	return 0;
}