La idea bsica de este mtodo de ordenacin es la mezcla(merge) de listas ya ordenadas.
Este algoritmo sigue la estrategia tpica de los algoritmos divide y vence. Los pasos que sigue se basan en dividir el problema de ordenar n elementos en dos subproblemas mas pequeos, de tamao mitad, de tal orma que una !ez ordenada cada mitad se mezclan para as resol!er el problema original. "on mas detalle# se ordena la primera mitad de la lista, se ordena la segunda mitad de la lista y una vez ordenadas su mezcla da lugar a una lista de elementos ordenada. A su vez, la ordenacin de la sublista mitad sigue los mismos pasos, ordenar la primera mitad, ordenar la segunda mitad y mezclar. La sucesi!a di!isin de la lista actual en dos $ace que el problema (n%mero de elementos) cada !ez sea ms pequeo& as $asta que la lista actual tiene ' elemento y por tanto se considera ordenada, es el caso base. ( partir de dos sublistas de un n%mero mnimo de elementos, empiezan las mezclas de pares de sublistas ordenadas, dando cada !ez lugar a sublistas ordenadas de cada !ez mas elementos (el doble de la anterior), $asta alcanzar la lista completa. EJEMPLO 1 Seguir la estrategia del algoritmo mergesort para ordenar la lista: 9 1 3 5 10 ! Las )igura ' muestra las sucesi!as di!isiones que origina el algoritmo. "ada di!isin se corresponde con una llamada recursi!a, por lo que a la !ez queda rele*ado el rbol de llamadas recursi!as. Figura 1. Sucesivas ivisi!"es e u"a #is$a %!r a#g!ri$&! &erges!r$. La mezcla comienza con las sublistas de un solo elemento, que dan lugar a otra sublista del doble de elementos ordenados. El proceso contin%a $asta que se construye la lista ordenada. La )igura + muestra qu sublistas se mezclan $asta que el proceso se propaga a la raz de las llamadas recursi!as y la lista queda ordenada. , ' - . '/ 0 1 , ' - . '/ 0 1 , ' - . '/ 0 1 , ' - . '/ 0 Figura ' Pr!gresivas &e(c#as e su)#is$as* e arri)a a)a+!. A#g!ri$&! &erges!r$ Este algoritmo de ordenacin se disea cilmente con ayuda de las llamadas recursi!as para di!idir las listas en dos mitades& posteriormente se in!oca al mtodo de mezcla de dos listas ordenadas. La delimitacin de las dos listas se $ace con tres ndices# primero, central y ultimo. Estos apuntan a los elementos del array de igual signiicado que los identiicadores. (s si se tiene una lista de '/ elementos los !alores de los ndices# primero = 0; ultimo = 9; central = (primero+ultimo)/2 = 4 La primera sublista comprende los elementos a 0 ...a 4 & y la segunda los elementos siguientes a 4+1 ... a 9. Los pasos del algoritmo para el array a # mergesort(a, primero, ultimo) si (primero < ultimo) Entonces central = (primero+ultimo)/2 mergesort(a, primero, central); ordena primera mitad mergesort(a, central+1, ultimo); ordena segunda mitad mezcla(a, primero, central, ultimo); fusiona las dos sublista in!si in El algoritmo de mezcla utiliza un !ector au2iliar, tmp"#, para realizar la usin entre dos sublistas ordenadas, que se encuentran en el !ector a"#, delimitadas por los ndices iz$a, me$io, $rc%a. ( partir de estos ndices se pueden recorrer las sublistas como se muestra en la )igura ..3 con las !ariables i, &. En cada pasada del algoritmo de mezcla se compara a"i# y a"&#, el menor se copia en el !ector au2iliar, tmp"#, y a!anzan los ndices de la sublista y del !ector au2iliar. La secuencia de )iguras ..3 muestra la mezcla de dos sublistas ordenadas. , ' - . '/ 0 1 ' , - . 0 '/ ' - . , 0 1 '/ ' - 0 . 1 , '/
a, Pu"$! e %ar$ia e" #a &e(c#a e !s su)#is$as !re"aas. ), Pri&era %asaa* se c!%ia e# e#e&e"$! a[i] e" tmp[z] - ava"(a" i, z.
c, Segu"a %asaa* se c!%ia e# e#e&e"$! a./0 e" $&%.(0 - ava"(a" /* (. , 1"ices - vec$!r au2i#iar es%u3s e 4 %asaas. Figura 5. Me(c#a e su)#is$as !re"aas.
El algoritmo de mezcla es lineal, debido a que $ay que realizar tantas pasadas como n%mero de elementos, en cada pasada se realiza una comparacin y una asignacin (comple*idad constante, '(1)). El n%mero de pasadas que realiza el algoritmo mergesort es igual a la parte entera de log 2 n. (e puede concluir que el tiempo de este algoritmo de ordenacin es '(n log n). C!i6icaci7" El tipo de datos del array $a de ser cualquier tipo comparable. El mtodo mezcla(), una !ez realizada sta, copia el array au2iliar tmp"# en el a"# con la utilidad arra)cop)() de la clase ()stem. - 1 '' i . , '/ 4 z tmp z - 1 '' i . , '/ 4 - tmp - 1 '' i . , '/ 4 - . tmp z - 1 '' i . , '/ 4 - . 1 , '/ tmp z static *oi$ mergesort($ou+le "# a, int primero, int ultimo) , int central; i (primero < ultimo) , central = (primero + ultimo)/2; mergesort(a, primero, central); mergesort(a, central+1, ultimo); mezcla(a, primero, central, ultimo); - - // mezcla $e $os su+listas or$ena$as static *oi$ mezcla($ou+le"# a, int iz$a, int me$io, int $rc%a) , $ou+le "# tmp = ne. $ou+le"a.lengt%#; int i, &, z; i = z = iz$a; & = me$io + 1; // +ucle para la mezcla, utiliza tmp"# como arra) au/iliar .%ile (i <= me$io 00 & <= $rc%a) , i (a"i# <= a"&#) tmp"z++# = a"i++#; else tmp"z++# = a"&++#; - // se mue*en elementos no mezcla$os $e su+listas .%ile (i <= me$io) tmp"z++# = a"i++#; .%ile (& <= $rc%a) tmp"z++# = a"&++#; // 1opia $e elementos $e tmp"# al arra) a"# ()stem.arra)cop)(tmp, iz$a, a, iz$a, $rc%a2iz$a+1); - La llamada al mtodo es# mergesort(a, 0, a.lengt% 2 1). RESOL8CIN DE PRO9LEMAS CON ALGORITMOS DE VUELTA ATRS. ( continuacin se resuel!en unos supuestos en los que se aplican los pasos que siguen los algoritmos basados en la b"s#ueda e$%austiva de la solucin probando con todas las alternati!as posibles que permitan ampliar la solucin parcial. En alguno de ellos no se siguen los mismos pasos que los realizado en el Salto del caballo o las &c%o reinas, sino que se adaptan para apro!ec$ar el $ec$o de agotar todas las posibilidades. Ge"erar #as is$i"$as variaci!"es* :&*". 5ado un con*unto de m elementos se quiere escribir los distintos subcon*untos de n elementos, sin que en un mismo subcon*unto pueda repetirse un elemento. 6n subcon*unto se dierenciar de otro por tener elementos dierentes, o bien, si son los mismos por el orden en que se encuentran. 7or e*emplo, sea 1 = ,a, +, c-. Los distintos subcon*untos de dos elementos que se pueden ormar, dierencindose uno de otro por el orden que ocupan, o bien por ser distintos# 3 4,2 = ,(a,+), (a,c), (+,a), (+,c), (c,a), (c,+)- 8e puede obser!ar que no se repiten los elementos en un mismo subcon*unto, no es !lido, por e*emplo, (a,a). A#g!ri$&! %ara res!#ver e# %r!)#e&a 8e sigue el esquema general de los algoritmos de vuelta atr's, aunque se tiene que introducir algunos cambios. ($ora interesa obtener todas las soluciones posibles, todos los subcon*untos, y no detener el proceso cuando se alcanza una solucin. Entonces no se disea un bucle condicional, que termina cuando se alcanza una solucin, sino un bucle que itera para cada uno de los elementos de tal orma que se agoten todas las posibilidades y as obtener todas las soluciones. El bucle# $es$e i = 1 %asta m %acer si <elemento i no orma parte $el su+con5unto6 entonces <incorporar elemento i al su+con5unto6 El ndice del bucle se corresponde con el elemento que pasa a ormar parte del subcon*unto o !ariacin actual. La tarea bsica en este problema es incorporar un nue!o elemento a la !ariacin actual. Este elemento es !lido si no est ya incorporado en la !ariacin, ya que no puede tener elementos repetidos. 6na !ariacin, subcon*unto de elementos, termina de ormarse cuando el n%mero de elementos es n (3 m,n ). Entonces el esquema del algoritmo que encuentra todas las soluciones# Ensa)ar(p7entero, 17 con5unto) inicio $es$e i = 1 %asta m %acer si <elemento i no orma parte $el su+con5unto6 entonces <incorporar elemento i al su+con5unto6 si p < n entonces Ensa)ar(p+1, 12elemento i ) sino escri+ir(su+con5unto) in2si in2si in2$es$e in La !ariable p lle!a la cuenta del n%mero de elementos que estn incluidos en la !ariacin en curso. "ada nue!a tarea, cada llamada recursi!a, incorpora un nue!o elemento (p+1), y lo retira. Re%rese"$aci7" e #!s a$!s 8e supone que el con*unto sobre el que se obtienen las !ariaciones son las letras del alabeto# c%ar cn5"# = ,8a8,8+8,8c8,8$8,8e8, ...-; Esta secuencia de letras se $acen corresponder con una secuencia de ndices enteros, en la que se toma como base 0# int c"# = ,0, 1, 2, 4, 4, ...-; 7ara guardar los elementos de la !ariacin actual se utiliza un array (int *"#), como $ay una correspondencia directa entre ndice y elemento, este array almacena %nicamente los ndices. En el momento de escribir por pantalla la !ariacin, los ndices guardados en *"# se transorman en los elementos. 7or e*emplo, si se estn ormando !ariaciones de + elementos y se tiene que *"#=,0,4-, se escriben cn5"*"0##,cn5"*"1## que se corresponden con cn5"0#, cn5"4# = 8a8, 8e8. C!i6icaci7" e# a#g!ri$&!. La entrada de datos que tiene el programa son los !alores m,n para as ormar 3m,n . El !alor de m y n no puede superar el m2imo de letras del con*unto que se considera. "uando se incorpora un elemento i a la !ariacin actual, este se retira del con*unto de ndices c"#, y para ello se asigna a la posicin i21 un !alor cla!e, se elige 91. En la vuelta atr's $ay que reponer el elemento, se $ace asignando a la posicin i21 el mismo !alor, i21 . 7ara comprobar si un elemento no est ya en la !ariacin actual, simplemente se pregunta si el ndice del elemento est en c"#. 5e estar es que no se incorpor anteriormente.
EJERCICIO 1 (scribir una clase #ue implemente el algoritmo #ue obtiene las variaciones de m elementos tomados de n en n. La clase tiene un constructor con los argumentos m, n. 6na !ez que se !alida estos !alores, se inicializa el con*unto de las letras sobre el que se obtiene las !ariaciones y se llama al mtodo recursi!o *ariaciones() que genera y muestra las !ariaciones. class 3ariacion , static inal int 1:;3E = 91; int m,n; c%ar cn5"# = ne. c%ar"2<#; int c"#= ne. int "2<#; int *"#; pu+lic 3ariacion(int !m, int !n) t%ro.s E/ception , m = !m; n = !n; i ((n 6 m)==(m 6 2<) == (n < 1) ==(m < 1)) t%ro. ne. E/ception(>Entra$a imposi+le, m = >+ m+ > n = >+ n); * = ne. int"n#; or (int & = 0; & < 2<; &++) , cn5"&# = (c%ar)(8a8 + &); c"&# = &; - *ariaciones(1, c); - pu+lic *oi$ *ariaciones(int p, int c"#) , int i; or (i = 1; i <= m; i++) , i (c"i21# == i21) // i no esta en la *ariaci?n actual , *"p21# = i21; // p21 $e+i$o a @n$ice +ase 0 i (p < n) , c"i21# = 1:;3E; *ariaciones(p+1,c); c"i21# = i21; // vuelta atrs7 repone el @n$ice - else , escri+ir(*); *"p21# = 0; - - - - pri*ate *oi$ escri+ir(int *"#) , int &; ()stem.out.print(> (>); or (& = 1; & <= n; &++) , c%ar c; c = (& < n A 8,8 7 8)8); ()stem.out.print(cn5"*"&21## + > > + c); - - - O)+e$!s ;ue $!$a#i(a" u" %es! !)+e$iv!. El planteamiento del problema es como sigue# se tiene un con)unto de ob)etos de pesos p1, p2, p4,...,pn; se #uiere estudiar si e$iste una seleccin de dic%os ob)etos #ue totalice e$actamente un peso v #ue se tiene como ob)etivo. 7or e*emplo, dados los ob*etos de pesos 4, 4 ,< ,2, 1 y el peso ob*eti!o * = 12. La seleccin ormada por los ob*etos primero, tercero y el cuarto totaliza el peso ob*eti!o, ya que la suma de sus pesos, 4 + < + 2 = 12. A#g!ri$&! %ara res!#ver e# %r!)#e&a La tarea b'sica a partir de la cual se amplia la solucin parcial al problema consiste en aadir un ob*eto nue!o, para probar si con su peso se alcanza el peso ob*eti!o, o se a!anza en la direccin de conseguirlo. Esta eleccin de un nue!o ob*eto ser la tarea bsica, la repeticin de esta tarea permitir completar la solucin, que en este problema es totalizar un peso ob*eti!o. 5e nue!o $ay una b%squeda sistemtica, e2$austi!a, de la solucin dando pasos $acia adelante. 8i se llega a un punto en el que no se consigue el peso ob*eti!o porque es superado, entonces se retrocede, vuelta atr's, para eliminar el ob*eto aadido y probar con otro. El proceso de seleccin termina en el momento de totalizar el peso ob*eti!o, o bien se $aya ensayado con todos los ob*etos. El n%mero de posibles elecciones de ob*etos con los que se pueden ensayar son los n ob*etos disponibles. Es inmediato que un ob*eto ya seleccionado no se puede !ol!er a elegir. Re%rese"$aci7" e #!s a$!s El peso de los ob*etos se supone que son !alores enteros. Entonces, la secuencia de ob*etos que orman el problema se representa en un array de tal orma que cada posicin almacena el peso de un ob*eto. "omo cada tarea, cada llamada recursi!a, selecciona un ob*eto nue!o, la bolsa que guarda los ob*etos de la seleccin actual se representa con un con*unto. 7ara simpliicar, el con*unto es un array donde se guardan los ndices de los ob*etos. 7osteriormente estos se recuperan a partir de dic$o ndice. C!i6icaci7" e# a#g!ri$&!. En la clase Seleccion&b)eto se implementa el algoritmo recursi!o& los atributos de la clase son los descritos anteriormente. El mtodo que implementa el algoritmo, seleccion(), prueba si el ob*eto can$i$ato puede aadirse a la seleccin. En caso airmati!o anota el ob*eto, acumulando su peso y metiendo el ndice que le corresponde en la bolsa. 7ara borrar la anotacin, en la vuelta atr's, se procede a la in!ersa. El constructor de la clase es importante para la correcta e*ecucin del mtodo recursi!o, ya que inicializa el n%mero de ob*etos que estn en la bolsa a cero, & = 0, y la !ariable booleana encontra$o a alse. Este s*itc% se pondr a true slo si el algoritmo recursi!o encuentra una seleccin. EJERCICIO ' (scribir la clase Seleccion&b)eto y una aplicacin #ue pida como datos de entrada los ob)etos y el peso #ue se #uiere conseguir. La clase dispone del mtodo entra$a() en el que se leen los pesos de los ob*etos y el peso ob*eti!o. La salida es el con*unto de ob*etos que orma la seleccin que totaliza el peso ob*eti!o, o bien un literal inormando de que no se encuentra la seleccin. 8e tiene en cuenta que los ndices del array tienen como base la posicin 0, de tal orma que un ob*eto seleccionado, can$i$ato, se guarda en la posicin del array can$i$ato21, para que as se corresponda con la posicin donde se almacen el peso del ob*eto. class (eleccion'+5eto , int n; int "#o+5s; int &; // cuenta los o+5etos en la +olsa int "# +olsa; int o+5eti*o; +oolean encontra$o; pu+lic (eleccion'+5eto() , n = & = 0; encontra$o = alse; -
i (suma < o+5eti*o) // ensa)a con siguiente o+5eto , seleccion(can$i$ato, suma); i (Hencontra$o) // vuelta atrs, se e/trae o+5eto , &22; suma 2= o+5s"can$i$ato91#; - - else // o+5etos totalizan el o+5eti*o encontra$o = true; - - - pu+lic *oi$ escri+ir(eleccion() , i (encontra$o) , ()stem.out.println(>In(elecci?n $e o+5etos7 >); or (int i = 1; i <= &; i++) , ()stem.out.println(> '+5eto > + (+olsa"i21#+1) + > peso7 > +o+5s"+olsa"i21##); - - else ()stem.out.println(>Eo %a) selecci?n Jue totalice el peso>); - - EJERCICIO 4.1 (scribir un m+todo recursivo #ue calcule el ,actorial de un n"mero n y un programa #ue pida un n"mero entero y escriba su ,actorial.. La componente base del mtodo recursi!o que calcula el actorial es que n 9 /, o incluso n 9 ' ya que en ambos caso el actorial es '. El problema se resuel!e recordando la deinicin e2puesta anteriormente del actorial# nH = 1 si n = 0 o n = 1 (componente base) nH = n.(n 2 1) si n 6 1 En la implementacin no se realiza tratamiento de error, que puede darse en el caso de calcular el actorial de un n%mero negati!o. import 5a*a.io.K; pu+lic class Lactorial , pu+lic static *oi$ main((tring"# ar)t%ro.s D'E/ception , int n; Buere$Cea$er entra$a = ne. Buere$Cea$er( ne. Dnput(treamCea$er(()stem.in)); $o , ()stem.out.print(>Dntro$uzca nFmero n7 >); n = Dnteger.parseDnt(entra$a.rea$:ine()); -.%ile (n < 0); ()stem.out.println(>In It> + n + >H= > + actorial(n)); -
static long actorial (int n) , i (n <= 1) return 1; else , long resulta$o = n K actorial(n 2 1); return resulta$o; - - - EJERCICIO 4.' -ostrar por pantalla el al,abeto, utilizando recursin indirecta. El mtodo main() llama a &e$!!A() con el argumento .Z. (la %ltima letra del alabeto). Este e2amina su parmetro c, si c est en orden alabtico despus que .A., llama a &e$!!B(), que inmediatamente in!oca a &e$!!A() pasndole un parmetro predecesor de c. Esta accin $ace que &e$!!A() !uel!a a e2aminar c, y nue!amente llame a &e$!!B(). Las llamadas continuan $asta que c sea igual a .A.. En este momento, la recursin termina e*ecutando System.out.print() !eintisis !eces y !isualiza el alabeto, carcter a carcter. pu+lic class ;la+eto , pu+lic static *oi$ main((tring "# a) , ()stem.out.println(); meto$o;(8M8); ()stem.out.println(); - static *oi$ meto$o;(c%ar c) , i (c 6 8;8) meto$oB(c); ()stem.out.print(c); - static *oi$ meto$oB(c%ar c) , meto$o;(22c); - - C#ase Ca)a##!Sa#$a!r class 1a+allo(alta$or , static inal int E = N; static inal int n = (E+1); pri*ate int "#"# ta+lero = ne. int"n#"n#; pri*ate +oolean e/ito; pri*ate int "#"#(;:O' = ,,2,1-, ,1,2-, ,21,2-, ,22,1-, ,22,21-, ,21,22-, ,1,22-, ,2,21--; pri*ate int /0, )0; // constructor pu+lic 1a+allo(alta$or(int /, int )) t%ro.s E/ception , i ((/ < 1) == (/ 6 E) == () < 1) == () 6 E)) t%ro. ne. E/ception(>1oor$ena$as uera $e rango>); /0 = /; )0 = ); or(int i = 1; i<= E; i++) or(int 5 = 1; 5<= E; 5++) ta+lero"i#"5# = 0; ta+lero"/0#")0# = 1; e/ito = alse; - pu+lic +oolean resol*erGro+lema() , salto1a+allo(/0, )0, 2); return e/ito; - pri*ate *oi$ salto1a+allo(int /, int ), int i) , int n/, n); int &; & = 0; // inicializa el con5unto $e posi+les mo*imientos $o , &++; n/ = / + (;:O'"&21#"0#; n) = ) + (;:O'"&21#"1#; // $etermina si nue*as coor$ena$as son aceptables i ((n/ 6= 1) 00 (n/ <= E) 00 (n) 6= 1) 00 (n) <= E) 00 (ta+lero"n/#"n)# == 0)) , ta+lero"n/#"n)#= i; // anota mo*imiento i (i < EKE) , salto1a+allo(n/, n), i+1); // se analiza si se %a completa$o la soluci?n i (He/ito) , // no se alcanz? la soluci?n ta+lero"n/#"n)# = 0; // se +orra anotaci?n - - else e/ito = true; // ta+lero cu+ierto - - .%ile ((& < N) 00 He/ito); - // muestra por pantalla los pasos $el ca+allo *oi$ escri+irOa+lero() , or(int i = 1; i <= E; i++) , or(int 5 = 1; 5 <= E; 5++) ()stem.out.print(ta+lero"i#"5# + > >); ()stem.out.println(); - - - EJERCICIO 4.5 (scribir una aplicacin #ue a partir de una casilla inicial del caballo resuelva el problema del /Salto del caballo/. La aplicacin lee las coordenadas iniciales, crea un ob*eto de la clase 0aballoSaltador y llama al mtodo resol*erGro+lema(). 8e escribe el contenido del tablero si $a resuelto el problema. import 5a*a.io.K; pu+lic class 1a+allo , pu+lic static *oi$ main((tring"# ar) , int /, ); +oolean solucion; Buere$Cea$er entra$a = ne. Buere$Cea$er( ne. Dnput(treamCea$er(()stem.in)); tr) , ()stem.out.println(>Gosicion inicial $el ca+allo. >); ()stem.out.print(> / = >); / = Dnteger.parseDnt(entra$a.rea$:ine()); ()stem.out.print(> ) = >); ) = Dnteger.parseDnt(entra$a.rea$:ine()); 1a+allo(alta$or mi1a+allo = ne. 1a+allo(alta$or(/,)); solucion = mi1a+allo.resol*erGro+lema(); i (solucion) mi1a+allo.escri+irOa+lero(); - catc% (E/ception m) , ()stem.out.println(>Eo se pu$o pro+ar el algoritmo, > + m); - - - C#ase Oc<!Rei"as class 'c%oCeinas , static inal int E = N; static inal int n = (E+1); pri*ate int "# reinas = ne. int"n#; pri*ate +oolean solucion; pu+lic +oolean solucionCeinas() , solucion = alse; ponerCeina(1); return solucion; - pri*ate *oi$ ponerCeina(int i) , int 5; 5 = 0; // inicializa posi+les mo*imientos $o , 5++; reinas"i# = 5; // prue+a a colocar reina i en ila 5, // a la *ez Jue$a anota$o el mo*imiento i (*ali$o(i)) , i (i < E) // no completa$o el pro+lema , ponerCeina(i+1); // *uelta atrPs i (Hsolucion) reinas"i# = 0; - else // to$as las reinas coloca$as solucion = true; - - .%ile(Hsolucion 00 (5 < N)); - pri*ate +oolean *ali$o(int i) , /K Dnspecciona si la reina $e la columna i es ataca$a por alguna reina coloca$a anteriormente K/ int r; +oolean li+re; li+re = true; or(r = 1; r <= i21; r++) , // no estQ en la misma ila li+re = li+re 00 (reinas"i#H= reinas"r#); // no estQ en alguna $e las $os $iagonales li+re = li+re 00 ((i + reinas"i#) H= (r + reinas"r#)); li+re = li+re 00 ((i 2 reinas"i#) H= (r 2 reinas"r#)); - return li+re; - *oi$ escri+irR+icacion() , or(int i = 1; i <= E; i++) , ()stem.out.println(>Ceina > + i + > = > + reinas"i#);
solucion = mireina.solucionCeinas(); i (solucion) mireina.escri+irR+icacion(); ()stem.e/it(0); - - EJERCICIO 4.= 1ado un con)unto de pesos, se #uiere escribir todas las combinaciones de ellos #ue totalicen un peso dado. El problema se resuel!e probando con todas las combinaciones posibles de los ob*etos disponibles. "ada !ez que la suma de los pesos de una combinacin sea igual al peso dado, se escribe los ob*etos de que consta. El problema se resuel!e modiicando el mtodo seleccion()de la clase (eleccion'+5eto. El atributo encontra$o ya no es necesario, el bucle tiene que iterar con todos los ob*etos, cada !ez que suma sea igual al peso ob*eti!o, o+5eti*o, se llama a escri+ir(eleccion(). ($ora, en la vuelta atr's siempre se borra de la bolsa la anotacin del ob*eto realizada, para as probar con los n ob*etos. import 5a*a.io.K; class (eleccionOo$os'+5eto , int n; int "#o+5s; int &; // cuenta los o+5etos en la +olsa int "# +olsa; int o+5eti*o; +oolean alguna = alse; pu+lic (eleccionOo$os'+5eto() , n = & = 0; -
pu+lic *oi$ entra$a()t%ro.s E/ception , Buere$Cea$er en= ne. Buere$Cea$er( ne. Dnput(treamCea$er(()stem.in));
(eleccionOo$os'+5eto so = ne. (eleccionOo$os'+5eto(); so.entra$a(); so.seleccion(0, 0); i (Hso.%a)(olucion()) ()stem.out.println(> Eo se encuentra solucion>);
()stem.e/it(0); - - EJERCICIO 4.4 (scribir la clase &ptima y una aplicacin #ue pida como datos de entrada los ob)etos 2valor, peso3 y el peso m'$imo #ue puede llevar el via)ante. El mtodo que resuel!e el problema !a a estar oculto, pri!ado, de tal orma que el interace, selecion'ptima(), inicializa los dos con*untos que representan a la seleccin actual y la ptima a con)unto4acio, simplemente poniendo el cardinal a cero. En este mtodo se suman los !alores asociados a cada ob*eto, que es el m2imo !alor alcanzable, y se asigna a total3alor. :ambin se pone a cero el atributo me5or3alor y llama al mtodo recursi!o. import 5a*a.io.K; class 'ptima , pri*ate int n; pri*ate int "#peso'+5s; pri*ate int "#*alor'+5s; pri*ate int car$inal;ctual; pri*ate int "# actual; pri*ate int car$inal'ptimo; pri*ate int "# optimo; pri*ate int pesoTa/imo; pri*ate int me5or3alor;
pu+lic 'ptima() , n = 0; -
pu+lic *oi$ entra$a()t%ro.s E/ception , Buere$Cea$er en= ne. Buere$Cea$er( ne. Dnput(treamCea$er(()stem.in));
$o , ()stem.out.print(>EFmero $e o+5etos7 >); n = Dnteger.parseDnt(en.rea$:ine()); -.%ile (n <= 1); peso'+5s = ne. int"n#; *alor'+5s = ne. int"n#; or (int 5 = 1; 5 <= n; 5++) , ()stem.out.print(>'+5eto > + 5 + >, peso = >); peso'+5s"521# = Dnteger.parseDnt(en.rea$:ine()); ()stem.out.print(>'+5eto> + 5 + >, *alor = >); *alor'+5s"521# = Dnteger.parseDnt(en.rea$:ine()); - $o , ()stem.out.print(>Geso mP/imo7 >); pesoTa/imo = Dnteger.parseDnt(en.rea$:ine()); -.%ile (pesoTa/imo <= 1); - pu+lic *oi$ seleccion'ptima() , int total3alor = 0; actual = ne. int"n#; optimo = ne. int"n#; me5or3alor = 0; car$inal;ctual = 0; or (int 5 = 0; 5 < n; 5++) total3alor += *alor'+5s"5#; seleccion'ptima(1, 0, total3alor); escri+ir(eleccion(); - pri*ate *oi$ seleccion'ptima(int i, int pt, int *a) , int *alE/clusion; i (pt + peso'+5s[i21] <= pesoTa/imo)// o+5eto i se inclu)e , car$inal;ctual++; actual"car$inal;ctual21# = i21; // @n$ices $el o+5eto i (i < n) seleccion'ptima(i+1, pt + peso'+5s[i21], *a); else // los n o+5etos pro+a$os i (*a 6 me5or3alor) // nue*o optimo , me5or3alor = *a; ()stem.arra)cop)(actual,0,optimo,0,car$inal;ctual); car$inal'ptimo = car$inal;ctual; - car$inal;ctual22 ; //*uelta atrPs, ensa)a e/clusi?n $e o+5eto i - /K proceso $e e/clusi?n $el o+5eto i para seguir la +FsJue$a sistemPtica con el o+5eto i+1 K/ *alE/clusion = *a 9 *alor'+5s[i21]; /K $ecrementa el *alor $el o+5eto e/clui$o K/ i (*alE/clusion 6 me5or3alor) /K se pue$e alcanzar una me5or selecci?n, sino poda la +FsJue$a K/ i (i < n) seleccion'ptima(i+1, pt, *alE/clusion); else , me5or3alor = *alE/clusion; ()stem.arra)cop)(actual,0,optimo,0,car$inal;ctual); car$inal'ptimo = car$inal;ctual; - - pu+lic *oi$ escri+ir(eleccion() , ()stem.out.println(>In(elecci?n $e o+5etos7 >); or (int i = 1; i <= car$inal'ptimo; i++) , ()stem.out.println(> '+5eto > + (optimo"i21#+1) + > peso7 > + peso'+5s"optimo"i21## + > *alor7 > + *alor'+5s"optimo"i21##); - - - pu+lic class E5ercicio!0SS , pu+lic static *oi$ main((tring args"#) t%ro.s E/ception , 'ptima so = ne. 'ptima(); so.entra$a(); so.seleccion'ptima(); ()stem.e/it(0); - -