You are on page 1of 22

ORDENACIN POR MEZCLAS: MERGESORT.

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;
-

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);
o+5s = ne. int"n#;
+olsa = ne. int"n#;
or (int 5 = 1; 5 <= n; 5++)
,
()stem.out.print(>'+5eto > + 5 + >, peso = >);
o+5s"521# = Dnteger.parseDnt(en.rea$:ine());
-
$o ,
()stem.out.print(>Geso o+5eti*o7 >);
o+5eti*o = Dnteger.parseDnt(en.rea$:ine());
-.%ile (o+5eti*o <= 1);
-
pu+lic *oi$ seleccion(int can$i$ato, int suma)
,
.%ile ((can$i$ato < n) 00 Hencontra$o)
,
can$i$ato++;
i ((suma + o+5s"can$i$ato21#) <= o+5eti*o)
,
&++; // es anota$o
+olsa"&21# = can$i$ato 2 1;
suma += o+5s"can$i$ato21#;

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#);

-
-
-
/K
E5ecuci?n
K/
pu+lic class 1o$iicacion!0S<2
,
pu+lic static *oi$ main((tring args"#)
,
+oolean solucion;
'c%oCeinas mireina = ne. 'c%oCeinas();

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));

$o ,
()stem.out.print(>EFmero $e o+5etos7 >);
n = Dnteger.parseDnt(en.rea$:ine());
-.%ile (n <= 1);
o+5s = ne. int"n#;
+olsa = ne. int"n#;
or (int 5 = 1; 5 <= n; 5++)
,
()stem.out.print(>'+5eto > + 5 + >, peso = >);
o+5s"521# = Dnteger.parseDnt(en.rea$:ine());
-

$o ,
()stem.out.print(>Geso o+5eti*o7 >);
o+5eti*o = Dnteger.parseDnt(en.rea$:ine());
-.%ile (o+5eti*o <= 1);
-
pu+lic *oi$ seleccion(int can$i$ato, int suma)
,
.%ile (can$i$ato < n)
,
can$i$ato++;
i ((suma + o+5s"can$i$ato21#) <= o+5eti*o)
,
&++; // es anota$o
+olsa"&21# = can$i$ato 2 1;
suma += o+5s"can$i$ato21#;
i (suma < o+5eti*o) // ensa)a con siguiente o+5eto
,
seleccion(can$i$ato, suma);
-
else
, // o+5etos totalizan el o+5eti*o
escri+ir(eleccion();
alguna = true;
-
// se +orra la anotaci?n
&22;
suma 2= o+5s"can$i$ato21#;
-
-
-
pu+lic *oi$ escri+ir(eleccion()
,
()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##);
-
-

+oolean %a)(olucion()
,
return alguna;
-
-
pu+lic class E5ercicio!0S4
,
pu+lic static *oi$ main((tring args"#) t%ro.s E/ception
,

(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);
-
-

You might also like