ADA Evaluación Alternativa. Ej. 1 Teoría y Práctica Curso 2006/2007 Teoría. Ejercicio 1. Dado el siguiente algoritmo: func alternativa06(ent/sal a: array[1..k] de Entero, i: Entero, j: Entero) dev (Entero: max) var terc, prim, seg: Entero alg si i = j ó a[i] < a[j] : max := a[j] otras : terc := ( j –i ) / 3 prim := i + terc seg := j – terc max := maximo6(a[i], a[prim], a[prim + 1], a[seg - 1], a[seg], a[j]) si max = a[i] ó max = a[prim]: max := alternativa06(a, i, prim) (*1) otras: si max = a[prim + 1] ó max = a[seg - 1]: max := alternativa06(a, prim +1, seg -1) (*2) otras: max := alternativa06(a, seg, j) (*3) fsi fsi fsi fin (a) ¿Cómo escogería el tamaño de problema n para cada llamada a la función recursiva alternativa06? (b) Determine el caso mejor y el tiempo de ejecución T(n) para la función alternativa06 con el tamaño de problema seleccionado en el apartado a). (c) Determine el caso peor y el tiempo de ejecución T(n) para la función alternativa06 con el tamaño de problema seleccionado en el apartado a). NOTAS: • Utilizar las constantes que se crean necesarias para englobar los costes de las operaciones. • Suponer que la llamada inicial es siempre alternativa06(a, 1, k). • El número de elementos del array recibido es potencia de 3. • La función maximo6 tiene un coste constante (puede llamarlo kmax6). Solución: a) n = j – i +1. El tamaño del problema corresponde con los elementos que van de i a j ambos incluidos. b) El caso mejor se da cuando en la primera llamada se cumple a[i] < a[j], es decir, cuando a[1] < a[k]. En ese caso: T(n) = K1 c) El caso peor se da cuando en todas las llamadas se incumple siempre que a[i] < a[j], y max = a[i] y max = a[prim], hasta llegar al tamaño 1. En cada llamada recursiva el tamaño del problema disminuye a la tercera parte, y sólo una llamada recursiva es posible dada la estructura de sentencias selectivas. La diferencia entre realizar una u otra llamada recursiva radica en que se realicen más o menos operaciones previas, pero todas estas operaciones previas son de tiempo constante. Veamos como se deduce el tamaño en las tres llamadas recursivas. (*1): tamaño n1 = prim – i + 1 = i + terc – i + 1 = terc +1 = ( j - i ) / 3 + 1 = [( n - 1) / 3] + 1 = [n /3 – 1] + 1= n / 3 Teniendo en cuenta que n = j – i + 1, y n es siempre potencia de 3, se deduce que [(n - 1) / 3] = [n/3 – 1] (*2): tamaño n2 = seg – 1 – (prim + 1) + 1= (j – terc) – 1 – ((i + terc) + 1) + 1 = j – i – 2*terc + 1=terc + 1 = n / 3 (*3): tamaño n3 = j – seg + 1 = j – (j – terc) + 1 = terc + 1 = n / 3 De los cálculos se deduce que n1 = n2 = n3 y por tanto el tamaño en todas las posibles llamadas es el mismo. K1 n=1 T(n) T( n ) + K2 + Kmax6 n > 1 3 K1 := Engloba las operaciones del caso base K2 := Coste de las operaciones del caso recursivo excepto la llamada recursiva y la llamada al método maximo6 Resolviendo el caso recursivo: T(n) - T( n ) = K3 . Realizando el cambio de variable n = 3k se deduce que: 3 tk – tk-1 = K3, La ecuación resultante es no homogénea. Usando b = 1 y d = 0, se obtiene una solución doble r1 = 1. Con esta raíz y deshaciendo el cambio de variable por log3 n = k se obtiene: T(n) = C1 + C2 log3n =T(n). Usando T(1) = K1 y T(3) = K1 + K2+ Kmax6 resulta C1 = K1 y C2 = K2+ Kmax6 Por tanto el orden es Θ(log n), que es a su vez cota superior e inferior. ADA Evaluación Alternativa. Ej. 1 Teoría y Práctica Curso 2006/2007 Prácticas. Distribución de libros en estanterías mediante técnica voraz. Un librero acaba de abrir un negocio en el que vende libros de diversos temas, que se ofrecen al público en una serie de estanterías. Dicho librero pretende minimizar el número de estanterías a utilizar, de forma que se optimice el espacio del local. Esto debe hacerlo teniendo en cuenta que todos los libros de una misma temática deberían estar siempre colocados en una misma estantería. En el caso de que no exista ninguna estantería con capacidad suficiente para una temática determinada, no se colocará dicha temática. Una estantería puede estar ocupada por libros de diversas temáticas mientras tenga capacidad para ello. Todas las estanterías tienen la misma capacidad, y todos los libros ocupan el mismo espacio. Vamos a modelar el problema a resolver mediante una clase denominada ProblemaLibreria, que posee los siguientes atributos: int [] numLibros.- array ordenado de forma decreciente tal que numLibros[t] indica el número de libros referentes a la temática t. int capacidadEstanterias.- indica el número de libros capaz de albergar cada una de las estanterías. int numMaximoEstanterias.- número de estanterías que caben en el local. a) Completa el código de la clase LibreriaVoraz que aparece a continuación, teniendo en cuenta que la estrategia voraz que se debe seguir consiste en recorrer las diferentes temáticas de mayor a menor número de unidades, de forma que se asigne una estantería a cada temática. La estantería elegida será aquélla que tenga espacio libre para la temática completa y que además sea la que tenga menor espacio libre. La solución se almacenará en el atributo estanteriaAsignada de la clase LibreriaVoraz, de forma que estanteriaAsignada[t] indica la estantería en la que se ubicará la temática t. En el caso de no encontrar ninguna estantería con capacidad suficiente para una temática determinada se asignará el valor -1. ADA Evaluación Alternativa. Ej. 1 Teoría y Práctica Curso 2006/2007 package soluciones.libreria; import esquemas.EsquemaVZ; import soluciones.EstrategiaSolucion; import problemas.ProblemaLibreria; extends EsquemaVZ implements EstrategiaSolucion public class LibreriaVoraz /* Array que indica el número de libros que compone cada temática. Se obtiene de la clase ProblemaLibreria */ int[] numLibros; /* Array que indica el espacio libre que tiene cada una de las estanterías en un momento del algoritmo, de forma que espacioLibreEstanterias[e]= n indica que la estantería e tiene sitio libre para n libros */ int[] espacioLibreEstanterias; // Capacidad de cada una de las estanterías int capacidadEstanterias; // Número máximo de estanterías int numMaximoEstanterias; // Array en el que se almacena la solución al problema int[] estanteriaAsignada; /* Representa el índice de la temática que se está analizando en cada momento del algoritmo */ int tematicaActual; /* Se utiliza para buscar la estantería más adecuada para tematicaActual en cada iteración del algoritmo */ int estanteriaAAsignar; public LibreriaVoraz(ProblemaLibreria pl) { this.numLibros = pl.getNumLibros(); this.capacidadEstanterias = pl.getCapacidad(); this.numMaximoEstanterias = pl.getNumMaximoEstanterias(); } public void procesamientoInicial() { } protected void inicializa() { this.espacioLibreEstanterias = new int[numMaximoEstanterias]; for (int i = 0; i < numMaximoEstanterias; i++) { this.espacioLibreEstanterias[i] = capacidadEstanterias; } estanteriaAsignada = new int[numLibros.length]; tematicaActual = 0; } protected boolean fin() { return (tematicaActual == numLibros.length); } { ADA Evaluación Alternativa. Ej. 1 Teoría y Práctica Curso 2006/2007 protected void seleccionaYElimina() { estanteriaAAsignar = -1; int minValor = Integer.MAX_VALUE; boolean enc = false; for (int i = 0; i < numMaximoEstanterias && !enc; i++) { if (espacioLibreEstanterias[i] >= numLibros[tematicaActual] && espacioLibreEstanterias[i] < minValor) { minValor = espacioLibreEstanterias[i]; estanteriaAAsignar = i; if(espacioLibreEstanterias[i] == numLibros[tematicaActual]){ enc = true; } } } if (estanteriaAAsignar != -1) { espacioLibreEstanterias[estanteriaAAsignar] = espacioLibreEstanterias[estanteriaAAsignar] - numLibros[tematicaActual]; } } protected boolean prometedor() { return true; } protected void anotaEnSolucion() { estanteriaAsignada[tematicaActual] = estanteriaAAsignar; tematicaActual++; } public void solucion() { voraz(); } public void procesamientoFinal() { } }