Soluciones Oficiales del Primer Examen Selectivo de la
V Olimpiada de Informática del Estado de Guanajuato


Baja el Examen Práctico en formato Adobe PDF.

El examen consistio en 3 problemas. La redacción estuvo a cargo de Marte Ramíres (Mars):

Problema Propuesto por
Herencia Mars
Plaza de las Ranas Mars
Fuga Mars

Las soluciones oficiales fueron programadas por Omar Ocegueda(Kayam) y Mars:

Solución Solución elaborada por
Herencia Mars
La Plaza de las Ranas Mars
Fuga Kayam

O baja todas las soluciones como archivo Zip.


Baja los evaluadores automaticos:

  1. Evaluar los 10 casos
  2. Evaluar un caso en particular

Los casos de prueba fueron elaborados por Kayam y Mars:

  1. Herencia
  2. La Plaza de las Ranas
  3. Fuga


Solución de Herencia

Ya que los límites nos lo permiten, emplearemos un algoritmo de BRUTE FORCE para resolver el problema. Para resolverlo empleamos un algoritmo que nos "cuente" números de N cifras tal que en cada lugar (donde va un dígito) tenga un "Tope" diferente. Por ejemplo, si tenemos 2 tipos de monedas con 2 4 de existencia entonces queremos ver todos los números de la siguente forma: 00, 10, 20, 01, 11, 21, 02, 12, 22, 03, 13, 23, 04, 14, 24. Si que realizamos todas las combinaciones en el caso extremo, lo que quiere decir que haremos 98 = 316 combinaciones posibles el cual es un número todavía suficientemente razonable para procesar (en una computadora rápida je).

Empleamos un arreglo de "Tope" que nos indica en cada posición hasta que número podemos llegar. Un arreglo en donde tenemos el número que se ha calculado.

El código en lenguaje C++ quedaría como el siguiente:

#include <stdio.h>
//---------------------------------------------------------------------------
FILE *Input,*Output;
int *CostoMoneda,SumaTotal,Mitad,Minimo;
///******************************
int Absoluto(int X)
{
if( X < 0 ) { return -X; }

return X;
}
///******************************
// 
void Checa(int N,int *Array)
{
int Temp,Suma,i;

Suma = 0;
for(i = 0; i < N; i++)
  { Suma += Array[i]*CostoMoneda[i]; }

Temp = Absoluto(2*Suma-SumaTotal);
if( Temp < Minimo )
  {
  Minimo = Temp;
  Mitad = Suma;
  }
}
///******************************
// Generamos los numeros de base variable.
void CuentaBaseVariable(int N,int *Tope)
{
// Inicializamos las variables que emplearemos
int i,Pos;
int *Array = new int[N+1];

// Comenzamos con el número de N + 1 ceros
for(i = 0; i < N; i++)
  { Array[i] = 0; }

// Pos nos indica en qué cifra estamos.
// Si Pos == N entonces quiere decir que ya contamos 
// todos los números
Pos = 0;
while( Pos < N )
  {
  // Mandamos a checar el número
  Checa(N,Array);
  
  // Sumamos uno a la primera cifra.
  Pos = 0;
  Array[Pos]++;
  
  // Si la cifra (Array[Pos]) en la posición Pos es igual a Tope[Pos]
  // entonces hacemos cero esa cifra y aumentamos en uno a la 
  // siguiente cifra y recorremos Pos en uno.
  while( Pos < N && Array[Pos] == Tope[Pos] )
    {
    Array[Pos] = 0;
    Pos++;
    Array[Pos]++;
    }
  }
  
// Liberamos la memoria.  
delete[] Array;
}
///******************************
int main(void)
{
int i,N,*Tope;
Input = fopen("Input.txt","r+t");

Minimo = 36000;
SumaTotal = 0;

fscanf(Input,"%d",&N);

Tope = new int[N];
CostoMoneda = new int[N];

for(i = 0; i < N; i++)
  {
  fscanf(Input,"%d",&Tope[i]);
  Tope[i]++;
  }
  
for(i = 0; i < N; i++)
  {
  fscanf(Input,"%d",&CostoMoneda[i]);
  SumaTotal += ((Tope[i]-1)*CostoMoneda[i]);
  }

fclose(Input);

CuentaBaseVariable(N,Tope);

Output = fopen("Output.txt","w+t");

fprintf(Output,"%d %d",Mitad,SumaTotal-Mitad);

fclose(Output);


        return 0;
}		
			


Regresar

Última actualización: 6/Enero/2005
Por Marte Ramírez