Cod sursa(job #433887)

Utilizator TokPhobiaCosoi Andrei TokPhobia Data 4 aprilie 2010 16:45:16
Problema Gutui Scor 70
Compilator cpp Status done
Runda teme_upb Marime 4.19 kb
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define FILEIN "gutui.in"
#define FILEOUT "gutui.out"
#define INFINIT 4294967295
#define DISPLAY 0

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

typedef struct elem {
	unsigned int val;
	elem *next;
} elem;

int insert(elem *start, gutuie *gutui, int h, int u) {
	unsigned int nivel_maxim_gutuie = (h-gutui->h)/u;
	int out_of_bounds = 0;
	
	//if (DISPLAY)  { printf("Gutuia noua poate fi pusa la cel mult %ud.\n", nivel_maxim_gutuie); fflush(stdout); }
	
	elem *p = start->next, *previous = start, *nou;
	
	//parcurgem de la final toate gutuile puse pana atunci
	while (p) {
		
		//if (DISPLAY) { printf("Suntem la gutuia de nivel %ud. Nivelul maxim curent e %ud. ", p->val, nivel_maxim_gutuie); fflush(stdout); }
		
		//daca gutuia curenta poate fi pusa mai tarziu decat gutuia noua
		if (p->val >= nivel_maxim_gutuie) {
			
			//if (DISPLAY) { printf("Trecem la urmatoarea\n"); fflush(stdout); }
			
			//trecem la urmatoarea gutuie
			if (p->val == nivel_maxim_gutuie) {
				if (nivel_maxim_gutuie)
					nivel_maxim_gutuie--;
				else
					out_of_bounds = 1;
			}
			previous = p;
			p = p->next;
			
		}
		
		//daca am ajuns la punctul la care am putea sa adaugam, verificam daca se poate
		else { 
			
			//if (DISPLAY) { printf("\nIncercam sa adaugam gutuia in lista (intre nivelele %ud si %ud)... ", previous->val, p->val); fflush(stdout); } 
			
			//daca o putem adauga
			if ((previous->val - nivel_maxim_gutuie) && (nivel_maxim_gutuie - p->val) && nivel_maxim_gutuie >= 0) {
				//if (DISPLAY) { printf("OK\n"); fflush(stdout); }
				
				//adaugam noua gutuie intre previous si p
				nou = (elem*)malloc(sizeof(elem));
				nou->val = nivel_maxim_gutuie;
				nou->next = p;
				previous->next = nou;
				return 1;
				
			}
			
			//daca nu se poate adauga
			else {
				//if (DISPLAY) { printf("Nu\n"); fflush(stdout); }
				return 0;
			}
			
		} //end verificare si adaugare
		
	}//end while
	
	
	//daca am ajuns pana aici inseamna ca ar trebui sa incercam la inceputul listei
	//if (DISPLAY) { printf("Incercam sa adaugam gutuia la inceputul listei (cu nivel %d), inaintea gutuii de nivel %ud ... ", nivel_maxim_gutuie, previous->val); fflush(stdout); }
	
	if ((previous->val - nivel_maxim_gutuie) && !out_of_bounds) {
		
		//if (DISPLAY) { printf("Okay\n"); fflush(stdout); }
		
		nou = (elem*)malloc(sizeof(elem));
		nou->val = nivel_maxim_gutuie;
		nou->next = previous->next;
		previous->next = nou;
		return 1;
		
	}
	
	//if (DISPLAY) { printf("Nu\n"); fflush(stdout); }
	return 0;
}

int main() {
	
	FILE *fin = fopen(FILEIN, "r"), *fout = fopen(FILEOUT, "w");
	int n, h, u, i;
	long int totalsum = 0;
	gutuie *gutui, *nou, *p, *prev;
	elem *start;
	
	//citim datele intr-o lista de gutui
	fscanf(fin, "%d %d %d", &n, &h, &u);
	
	gutui = (gutuie*)malloc(sizeof(gutuie));
	fscanf(fin, "%d %d", &gutui->h, &gutui->g);
	gutui->next = NULL;
	
	for (i=2; i<=n; i++) {
		nou = (gutuie*)malloc(sizeof(gutuie));
		fscanf(fin, "%d %d", &nou->h, &nou->g);
		
		p = gutui;
		//daca trebuie pusa in capul listei
		if (p->g <= nou->g) {
			nou->next = p;
			gutui = nou;
			continue;
		}
		
		//daca am ajuns aici atunci sigur nu trebuie pusa in capul listei
		prev = p;
		p = p->next;
		while (p && p->g > nou->g) {
			prev = p;
			p = p->next;
		}
		prev->next = nou;
		nou->next = p;

	}	
	//sfarsit citit date
	
	//if (DISPLAY) {printf("Am citit toate datele\n\n"); fflush(stdout);}
	
	//initializam lista de gutui care le culegem
	start = (elem*)malloc(sizeof(elem));
	start->val = INFINIT;
	start->next = NULL;
	
	//luam gutuile in ordinea descrescatoare a greutatii
	p = gutui;
	for (i=1; i<=n; i++) {
		
		//if (DISPLAY) { printf("Incerc sa adaug (%d, %d) la lant. ", p->g, p->h); fflush(stdout); }
		
		//vedem daca putem pune gutuia maxima in lista
		if (insert(start, p, h, u)) {
				
			//if (DISPLAY) { printf("Am adaugat gutuia\n"); fflush(stdout); }
				
			totalsum += p->g;
			
		}
		//else if (DISPLAY) { printf("Nu am adaugat gutuia\n"); fflush(stdout); }
		
		//if (DISPLAY) printf("Suma partiala %ld\n", totalsum);
		
		p = p->next;
	}
	
	//if (DISPLAY) printf("Suma maxima finala: %ld\n", totalsum);
	
	fprintf(fout, "%ld\n", totalsum);
	
	fclose(fin);
	fclose(fout);
	
	return 0;
}