Cod sursa(job #435479)

Utilizator flo2006NuPreaConteaza flo2006 Data 7 aprilie 2010 15:10:43
Problema Gutui Scor 10
Compilator c Status done
Runda teme_upb Marime 5.42 kb
/*
							======================== TEMA 1 PA =========================
											===Problema 2 - Gutui===
											Student : PALITA FLORIAN
												GRUPA   : 324 CC
							=============================================================
*/

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

//Structura care retine pentru o gutuie inaltimea si greutatea
typedef struct gutui	{
	int inaltime;
	int greutate;
} gutui;

//Structura unui nivel din copac
typedef struct niv		{
	int greutati[10000];
	int lung;
} niv;

int N;					//Numarul de gutui
int H;					//Inaltimea maxima la care ajunge
int U;					//Inaltimea cu care se ridica
FILE *g;				//Fisier de iesire
gutui p[100000];		//Vector cu cele N perechi inaltime - greutate
niv nivele[10000];		//Vector cu nivelele gutuiului
int numar_nivele = 0;	//Numarul de nivele
int g_gutui[100000];	//Vector cu greutatile gutuilor
int marcaje[100000];	//Vector cu marcaje ( 1-daca gutuia e pe nivelul actual , 0-daca nu )
int n_gutui[100000];	//Vector cu nivelul pe care e gutuia

//Functia de comparare pentru qsort
int compare (const void * a, const void * b)	{
  return ( *(int*)a - *(int*)b );
}

//Functie pentru preluarea datelor din fisierul de intrare
void input_data()	{
	FILE *f;
	int i, j = 0;
	f = fopen("gutui.in", "r");
	fscanf(f, "%d %d %d\n", &N, &H, &U);
	for (i = 0 ; i < N ; i++)	{	
		fscanf(f, "%d %d\n", &p[i].inaltime, &p[i].greutate);
		marcaje[i] = 0;
		g_gutui[j] = p[i].greutate;
		j++;
	}
	fclose(f);
}

//Functie ce partitioneaza pe nivele gutuile
void partition()	{
	int inf, sup, i;
	sup = H;
	inf = H - U;
	while (inf > 0)	{
		nivele[numar_nivele].lung = 0;
		for (i = 0 ; i < N ; i++)
			if ((p[i].inaltime > inf) && (p[i].inaltime <= sup))	{
				nivele[numar_nivele].greutati[nivele[numar_nivele].lung] = g_gutui[i];
				n_gutui[i] = numar_nivele;
				nivele[numar_nivele].lung++;
			}
		numar_nivele++;
		sup = inf;
		inf = inf - U;
	}
	if (inf == 0)	{
		nivele[numar_nivele].lung = 0;
		for (i = 0 ; i < N ; i++)
			if ((p[i].inaltime > inf) && (p[i].inaltime <= sup))	{
				nivele[numar_nivele].greutati[nivele[numar_nivele].lung] = g_gutui[i];
				n_gutui[i] = numar_nivele;
				nivele[numar_nivele].lung++;
			}
		numar_nivele++;
	}
	if (inf < 0)	{
		nivele[numar_nivele].lung = 0;
		for (i = 0 ; i < N ; i++)
			if ((p[i].inaltime >= 0) && (p[i].inaltime <= sup))	{
				nivele[numar_nivele].greutati[nivele[numar_nivele].lung] = g_gutui[i];
				n_gutui[i] = numar_nivele;
				nivele[numar_nivele].lung++;
			}
		numar_nivele++;
	}
}

//Functie ce calculeaza maximul greutatii de pe nivelul maxim
int maxim_nivel()	{
	int i, max = 0, j;
	if (nivele[0].lung == 0)
		return 0;
	for (i = 0 ; i < nivele[0].lung ; i++)
		if (nivele[0].greutati[i] > max)	
			for (j = 0 ; j < N ; j++)
				if ((g_gutui[j] == nivele[0].greutati[i]) && (marcaje[j] == 0) && (n_gutui[j] == 0))
					max = nivele[0].greutati[i];
	return max;
}

//Functie care sterge primul nivel , dupa culegerea unei gutui
void stergeNivel()	{
	int i, j;
	for (i = 1 ; i < numar_nivele ; i++)	{
		nivele[i-1].lung = nivele[i].lung;
		for (j = 0 ; j < nivele[i-1].lung ; j++)
			nivele[i-1].greutati[j] = nivele[i].greutati[j];
	}
	numar_nivele--;
	for (i = 0 ; i < N ; i++)
		n_gutui[i]--;
}

int main()	{
	int max, i, j, G = 0, u = 100, temp, ok;
	int g_gutui2[100000],ordine[100000];
	input_data();
	partition();
	while ((numar_nivele > 0) && ( u != 0))	{
		//Preiau maximul de pe nivelul cel mai de sus
		max = maxim_nivel();	
		//Marchez gutuile de pe nivel cu 1 pentru ca nu mai pot fi culese
		for (i = 0 ; i < N ; i++)
			if (n_gutui[i] == 0)	
				marcaje[i] = 1;
		u = 0;
		//Creez vectorul gutui2 cu greutatile care mai pot fi culese
		for (i = 0 ; i < N ; i++)
			if (marcaje[i] == 0)	{
				ordine[u] = i;
				g_gutui2[u] = g_gutui[i];
				u++;
			}
		//Sortez vectorul gutui2 crescator si sortez si ordinea lor	
		//qsort(g_gutui2, u, sizeof(int), compare);
		for (i = 0 ; i < u - 1 ; i++)
			for (j = i + 1 ; j < u ; j++)	
				if (g_gutui2[i] > g_gutui2[j])	{
					temp = g_gutui2[i];
					g_gutui2[i] = g_gutui2[j];
					g_gutui2[j] = temp;
					temp = ordine[i];
					ordine[i] = ordine[j];
					ordine[j] = temp;
				}
				else 
					if ((g_gutui2[i] == g_gutui2[j]) && (n_gutui[ordine[i]] < n_gutui[ordine[j]]))	{
						temp = g_gutui2[i];
						g_gutui2[i] = g_gutui2[j];
						g_gutui2[j] = temp;
						temp = ordine[i];
						ordine[i] = ordine[j];
						ordine[j] = temp;
					}
		ok = 0;
		//Caut al doilea maxim
		for (i = u - 2 ; i >= 0 ; i--)
			if (g_gutui2[i] < g_gutui2[u-1])	{
				ok = 1;
				break;
			}
		if (max == 0)	{
			//Daca nivelul maxim nu are gutui , iau maximul din ce a mai ramas , si bifez
			G += g_gutui2[u-1];
			marcaje[ordine[u-1]] = 1;
		}
		else
			if (u == 1 || ok == 0)	{
				//Daca pe nivelul maxim am cel putin o gutuie , si in restul copacului mai e doar una , o culeg pe aceasta de sus
				G += max;
			}
			else
				//Daca sunt mai multe gutui in restul copacului si gutuia de pe nivelul maxim e mai grea decat al doilea maxim din rest o culeg
				if (max >= g_gutui2[i])	{
					G += max;
				}
				else	{
						G += g_gutui2[u-1];
						marcaje[ordine[u-1]] = 1;
					} 			
		u = 0;
		for (i = 0 ; i < N ; i++)	
			if (marcaje[i] == 0)
				u++;
		stergeNivel();
	}
	g = fopen("gutui.out", "w");
	fprintf(g, "%d\n", G);
	fclose(g);
	return 0;
}