Cod sursa(job #434813)

Utilizator MatwixGherasim Alin Matwix Data 6 aprilie 2010 16:35:39
Problema Gutui Scor 100
Compilator c Status done
Runda teme_upb Marime 2.92 kb
/*
 * gutui.c
 *
 *  Created on: Apr 4, 2010
 *      Author: matwix
 */

#include <stdio.h>
#include <stdlib.h>

// Lista dublu inlantuita

typedef struct list_el {
   long int inaltime, greutate, nivel;
   struct list_el * next, * prev;
} * List;

// Calculez maximul dintr-o lista

List maxim(List *v, long int n){
	long int i, max = 0;
	List l, max_l = NULL;
		l = v[n];
		while (l != NULL){
			if (l -> greutate > max){
				max = l -> greutate;
				max_l = l;
			}
			l = l -> next;
		}
	return max_l;
}

// Calculez maximul dintr-un vector de elemente

List max_vect(List *v, long int min, long int max){
	long int j, maxi = 0;
	List max_l = NULL;
	for(j = min; j < max; j++){
		if(v[j] != NULL)
			if (maxi < v[j] -> greutate){
				maxi = v[j] -> greutate;
				max_l = v[j];
			}
	}
	return max_l;
}

// Verific daca un vector de liste este gol

int gol(List *v, long int min, long int max){
	long int i;
	int boo = 0;
	for(i = min; i <= max; i++)
		if (v[i] != NULL)
			boo = 1;
	return boo;
}

int main(){
	long int n, max = 0, H, U, aux1, aux2, i, nivel_max, nivel_min=2147000000, nivel_curent, j;
	List *v_max; // Vector de noduri
	FILE *fin = fopen("gutui.in", "r");
	FILE *fout = fopen("gutui.out", "w");
	List *vector; // Un vector de liste (dictionar) unde indicele este nivelul fructului
	List l;

	fscanf (fin, "%ld %ld %ld", &n, &H, &U);

	nivel_max = H/U;

	vector = (List*)malloc((H/U+1)*sizeof(List));
	v_max = (List *)malloc((H/U+1)*sizeof(List));

	/* Citesc elementele si le adaug in dictionar in functie de nivel*/

	for (i = 0; i < n; i++){
		fscanf(fin, "%ld %ld", &aux1, &aux2);
		l = (List)malloc(sizeof(struct list_el));
		l -> inaltime = aux1;
		l -> greutate = aux2;
		l -> nivel = H/U - (H-aux1)/U;
		if(l -> nivel < nivel_min)
			nivel_min = l ->nivel;
		if (vector[l -> nivel] != NULL){
			l -> prev = NULL;
			l -> next = vector[l -> nivel];
			vector[l -> nivel] -> prev = l;
			vector[l -> nivel] = l;
		}else{
			l -> prev = NULL;
			l -> next = NULL;
			vector[l -> nivel] = l;
		}
	}

	i = nivel_min;

	// Creez un vector de maxime pentru fiecare nivel

	for (j = nivel_min; j <= nivel_max; j++){
		v_max[j] = maxim(vector, j);
	}

	while (nivel_max >= i && gol(vector, nivel_min, nivel_max)){
		l = max_vect(v_max, nivel_min, i+1); // iau elementul maxim de pe cel mai mic nivel

		// Sterg nodul din lista nivelului

		if (l != NULL){
			nivel_curent = l -> nivel;
			max += l -> greutate;
			if (l -> prev == NULL){
				vector[l -> nivel] = l -> next;
				if (l -> next != NULL)
					l -> next -> prev = NULL;
				free(l);
			}else{
				if (l -> next == NULL){
					l -> prev -> next = NULL;
					free(l);
				}else{
					l -> prev -> next = l -> next;
					l -> next -> prev = l -> prev;
					free(l);
				}
			}

			// Recalculez maximul de pe nivelul de unde sterg nodul

		v_max[nivel_curent] = maxim(vector, nivel_curent);
		}
		i++; // incrementez nivelul curent
	}

	fprintf(fout, "%ld", max);

	fclose(fin);
	fclose(fout);

	return 0;
}