Cod sursa(job #436617)

Utilizator Marius_AMarius Marius_A Data 8 aprilie 2010 18:17:09
Problema Gutui Scor 100
Compilator c Status done
Runda teme_upb Marime 4.56 kb
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define DEBUG 0

typedef struct gutuie{
	int greut;//ce greutate are
	int inalt;//la ce inaltime
	int rez;//cate gutui maxim pot culege inainte sa nu mai ajung la aceasta gutuie
			//altfel spus, ce rezistenta are :P
}gutuie;


struct node
{
	int priority;
	int info;
	struct node *next;
}*start,*q,*temp,*noul;

typedef struct node *N;

//functia de insertie
void insert(int itprio)
{
	noul=(struct node *)calloc(1,sizeof(struct node));

	noul->priority=itprio;

	if(start==NULL || itprio<start->priority)
	{
		noul->next=start;
		start=noul;
	}
	else
	{
		q=start;
		while(q->next != NULL && q->next->priority<=itprio)
			q=q->next;
		(noul->next)=(q->next);
		q->next=noul;
	}
}

int peek()
{
	if(start==NULL)
		return 0;
	else
		return start->priority;
}

//delete
void del()
{
	if(start==NULL)
	{
		printf("\n eroare");
	}
	else
	{
		noul = start;
		start=start->next;
		free(noul);
	}
}

void swap (gutuie *a, gutuie *b)
{
	gutuie c = *a;
	*a = *b;
	*b = c;
}

//sortare gutui, mergesort
void qsort_r (gutuie* primul, gutuie* ultimul)
{
	gutuie *mic = primul;
	gutuie *mare = ultimul;
	gutuie  pivot = *(primul+(ultimul-primul)/2);

	while (mic <= mare)
	{
		while ((*mic).rez < pivot.rez || ((*mic).rez == pivot.rez && (*mic).greut > pivot.greut) ) mic++;
		while (pivot.rez < (*mare).rez || (pivot.rez == (*mare).rez && pivot.greut > (*mare).greut)) mare--;

		if (mic < mare) swap (mic++, mare--);
		else mic++;
	}

	if (primul < mare) 
		qsort_r (primul, mare);
	if (mare < ultimul) 
		qsort_r (mare+1, ultimul);
}


int main()
{

	FILE *input;
	FILE *output;

	int i,j,m,n;

	//nr gutui, inaltimea, si cu cat se ridica
	int Nr,H,U;

	int *inaltimi;
	int *greutati;
	int *rezista;

	gutuie *vec;

	int rezultat=0;
	int remains;
	int alese;

	int nr_gutui;
	int diferenta,nivel,niv_curent,alesi_pe_nivel;

	//citirea datelor
	input = fopen("gutui.in","r");
	fscanf(input,"%d %d %d",&Nr,&H,&U);

	//cate un vector pentru fiecare
	inaltimi = (int*)calloc(Nr,sizeof(int));
	greutati = (int*)calloc(Nr,sizeof(int));
	rezista = (int*)calloc(Nr,sizeof(int));

	//un vector de gutui
	vec = (gutuie*)calloc(Nr,sizeof(gutuie));

	start = NULL;

	//citesc inaltimile si greutatile
	for(i=0;i<Nr;i++){
		fscanf(input,"%d %d",&(vec[i].inalt),&(vec[i].greut));
	}

	fclose(input);


	//calculez fiecare gutuie la cate culegeri ( de alte gutui ) rezista
	for(i=0;i<Nr;i++)
		vec[i].rez = (H-vec[i].inalt)/U+1;

	//sortez gutuile in functie de rezistenta (primar) si apoi de greutate(pt rezistente egale)
	qsort_r(vec,vec+Nr-1);

	if(DEBUG)
	for(i=0;i<Nr;i++)
		printf("%d %d %d\n", vec[i].greut,vec[i].rez,vec[i].inalt);

	remains = 0;

	nivel = vec[0].rez;
	niv_curent = nivel;

	if(DEBUG)printf("incep");

	//inserez primele gutui, cele care nu rezista deloc, in coada prioritara
	//din aceste gutui am voie sa aleg maxim una
	alesi_pe_nivel=0;

	for(i=0;i<nivel&&vec[i].rez==nivel;i++){
		alesi_pe_nivel+=1;
		insert(vec[i].greut);
	}
	
	diferenta =0;
	alese=alesi_pe_nivel;

	//iterez pe toate gutuile
	for(i=alesi_pe_nivel;i<Nr;i++)
	{
		if(DEBUG)display();
		if(DEBUG)printf("\n-%d-  %d %d\n",i,vec[i].greut,vec[i].rez);

		//daca am trecut la alt nivel
		if(vec[i].rez > nivel)
		{
			niv_curent = vec[i].rez;
			//am voie sa aleg maxim diferenta dintre acest nivel si penultimul 
			//gutui
			diferenta = niv_curent - alese;
			nivel=niv_curent;

			//aleg pe cea mai grea
			insert(vec[i].greut);
			alese+=1;
			//diferenta scade cu 1
			diferenta -=1;
			//am ales o gutuie pe acest nivel
			alesi_pe_nivel =1;
		}
		else
		{//daca mai am inca loc sa aleg gutui de pe acest nivel, aleg pe cea mai grea
			if(diferenta>0){

				insert(vec[i].greut);
				alese+=1;
				diferenta -=1;
				alesi_pe_nivel+=1;
			}
			else
			{ //altfel, pentru restul de gutui de pe acest nivel, ma uit sa vad daca sunt mai grele
			  //decat vreo gutuie aleasa de pe un nivel anterior, caz in care fac schimb
			  //aici ma ajuta coada prioritara, pentru ca ma uit direct la cele mai usoare gutui alese

				if(alesi_pe_nivel < niv_curent){
					if(peek() < vec[i].greut){
						del();
						insert(vec[i].greut);
						alesi_pe_nivel+=1;
					}
				}
			}
		}
	}

	diferenta =0;

	//calculez greutatea finala
	while(start != NULL)
	{
		diferenta += peek();
		del();
	}

	output=fopen("gutui.out","w");
	fprintf(output,"%d",diferenta);
	fclose(output);
	//getchar();
	return 0;
}