You are on page 1of 10

Backtracking

* Introducción
* La vuelta del caballo
* El problema de las ocho reinas
* El problema de la mochila (selección óptima)
* Problemas propuestos

Introducción
Los algoritmos de vuelta atrás se utilizan para encontrar soluciones a un problema. No
siguen unas reglas para la bs!ueda de la solución" simplemente una bs!ueda
sistemática" !ue más o menos viene a signi#icar !ue ha$ !ue probar todo lo posible
hasta encontrar la solución o encontrar !ue no e%iste solución al problema. Para
conseguir este propósito" se separa la bs!ueda en varias bs!uedas parciales o
subtareas. &simismo" estas subtareas suelen incluir más subtareas" por lo !ue el
tratamiento general de estos algoritmos es de naturaleza recursiva.
'Por !u( se llaman algoritmos de vuelta atrás). Por!ue en el caso de no encontrar una
solución en una subtarea se retrocede a la subtarea original $ se prueba otra cosa
distinta (una nueva subtarea distinta a las probadas anteriormente).
Puesto !ue a veces nos interesa conocer mltiples soluciones de un problema" estos
algoritmos se pueden modi#icar #ácilmente para obtener una nica solución (si e%iste) o
todas las soluciones posibles (si e%iste más de una) al problema dado.
Estos algoritmos se aseme*an al recorrido en pro#undidad dentro de un gra#o (ver
sección de gra#os" estructuras de datos" $ recorrido de gra#os" algoritmos)" siendo cada
subtarea un nodo del gra#o. El caso es !ue el gra#o no está de#inido de #orma e%pl+cita
(como lista o matriz de ad$acencia)" sino de #orma impl+cita" es decir" !ue se irá creando
segn avance el recorrido. & menudo dicho gra#o es un árbol" o no contiene ciclos" es
decir" al buscar una solución es" en general" imposible llegar a una misma solución x
partiendo de dos subtareas distintas a $ b, o de la subtarea a es imposible llegar a la
subtar(a b $ viceversa.
-rá#icamente se puede ver as+.

& menudo ocurre !ue el árbol o gra#o !ue se genera es tan grande !ue encontrar una
solución o encontrar la me*or solución entre varias posibles es computacionalmente mu$
costoso. En estos casos suelen aplicarse una serie de restricciones" de tal #orma !ue se
puedan podar algunas de las ramas" es decir" no recorrer ciertas subtareas. Esto es
posible si llegado a un punto se puede demostrar !ue la solución !ue se obtendrá a
partir de ese punto no será me*or !ue la me*or solución obtenida hasta el momento. /i
se hace correctamente" la poda no impide encontrar la me*or solución.
& veces" es imposible demostrar !ue al hacer una poda no se est( ocultando una buena
solución. /in embargo" el problema !uizás no pida la me*or solución" sino una !ue sea
razonablemente buena $ cu$o coste computacional sea bastante reducido. Esa es una
buena razón para aumentar las restricciones a la hora de recorrer un nodo. 0al vez se
pierda la me*or solución" pero se encontrará una aceptable en un tiempo reducido.
Los algoritmos de vuelta atrás tienen un es!uema gen(rico" segn se bus!ue una o
todas las soluciones" $ puede adaptarse #ácilmente segn las necesidades de cada
problema. & continuación se e%ponen estos es!uemas" e%tra+dos de 1irth (ver
2ibliogra#+a). Los blo!ues se agrupan con begin $ end" e!uivalentes a los corchetes de
3" además están tabulados.
- esquema para una solución:
procedimiento ensayar (paso : TipoPaso)
repetir
| seleccionar_candidato
| if aceptable then
| begin
| anotar_candidato
| if solucion_incompleta then
| begin
| ensayar(paso_siguiente)
| if no acertado then borrar_candidato
| end
| else begin
| anotar_solucion
| acertado <- cierto;
| end
hasta que (acertado = cierto) o (candidatos_agotados)
fin procedimiento

- esquema para todas las soluciones:
procedimiento ensayar (paso : TipoPaso)
para cada candidato hacer
| seleccionar candidato
| if aceptable then
| begin
| anotar_candidato
| if solucion_incompleta then
| ensayar(paso_siguiente)
| else
| almacenar_solucion
| borrar_candidato
| end
hasta que candidatos_agotados
fin procedimiento

Por ltimo" se e%ponen una serie de problemas t+picos !ue se pueden resolver
#ácilmente con las t(cnicas de vuelta atrás. El primero !ue se e%pone es mu$ conocido.
/e trata de la vuelta del caballo. 4uchos problemas de los pasatiempos de los
periódicos pueden resolverse con la a$uda de un ordenador $ en esta 5eb se muestran
algunos de ellos.

La vuelta del caballo
/e dispone de un tablero rectangular" por e*emplo el tablero de a*edrez" $ de un caballo"
!ue se mueve segn las reglas de este *uego. El ob*etivo es encontrar una manera de
recorrer todo el tablero partiendo de una casilla determinada" de tal #orma !ue el
caballo pase una sola vez por cada casilla. 6na variante es obligar al caballo a volver a
la posición de partida en el ltimo movimiento.
Por ltimo se estudiará como encontrar todas las soluciones posibles partiendo de una
misma casilla.
Para resolver el problema ha$ !ue realizar todos los movimientos posibles hasta !ue $a
no se pueda avanzar" en cu$o caso ha$ !ue dar marcha atrás" o bien hasta !ue se cubra
el tablero. &demás" es necesario determinar la organización de los datos para
implementar el algoritmo.
7 '3ómo se mueve un caballo). Para a!uellos !ue no sepan *ugar al a*edrez se muestra
un grá#ico con los ocho movimientos !ue puede realizar. Estos movimientos serán los
ocho candidatos.
3on las coordenadas en las !ue se encuentre el caballo $ las ocho coordenadas relativas
se determina el siguiente movimiento. Las coordenas relativas se guardan en dos
arra$s.
e*e% 8 9:" ;" 7;" 7:" 7:" 7;" ;" :<
e*e$ 8 9;" :" :" ;" 7;" 7:" 7:" 7;<
El tablero" del tama=o !ue sea" se representará mediante un arra$ bidimensional de
nmeros enteros. & continuación se muestra un grá#ico con un tablero de tama=o >%>
con todo el recorrido partiendo de la es!uina superior iz!uierda.

3uando se encuentra una solución" una variable !ue se pasa por re#erencia es puesta a
; (cierto). Puede hacerse una variable de alcance global $ simpli#icar un poco el código"
pero esto no siempre es recomendable.
Para codi#icar el programa" es necesario considerar algunos aspectos más" entre otras
cosas no salirse de los l+mites del tablero $ no pisar una casilla $a cubierta (selección del
candidato). /e determina !ue ha$ solución cuando $a no ha$ más casillas !ue recorrer.
& continuación se e%pone un código completo en 3" !ue recubre un tablero cuadrado de
lado N partiendo de la posición (?"?).
#include <stdio.h
#de!ine " #
#de!ine ncuad "$"
%oid mo%er(int tablero&'&"'( int i( int pos_)( int pos_y( int $*);
const int e+e)&,' = - -.(-/(-/(-.( .( /( /( . 0(
e+ey&,' = - -/(-.( .( /( /( .(-.(-/ 0;
int main(%oid)
-
int tablero&"'&"'; 1$ tablero del caballo. $1
int i(+(*;
1$ iniciali2a el tablero a cero $1
!or (i = 3; i < "; i44)
!or (+ = 3; + < "; +44)
tablero&i'&+' = 3;
1$ pone el primer mo%imiento $1
tablero&3'&3' = .;
mo%er(tablero(/(3(3(5*);
i! (*) - 1$ hay solucion: la muestra. $1
!or (i = 3; i < "; i44) -
!or (+ = 3; + < "; +44)
print!(678d 6( tablero&i'&+');
putchar(9:n9);
0
0
else
print!(6:n"o e)iste solucion:n6);
return 3;
0
%oid mo%er(int tablero&'&"'(int i( int pos_)( int pos_y( int $*)
-
int ;( u( %;
; = 3;
$* = 3;
do -
u = pos_) 4 e+e)&;'; % = pos_y 4 e+ey&;'; 1$ seleccionar candidato $1
i! (u = 3 55 u < " 55 % = 3 55 % < ") - 1$ esta dentro de los
limites< $1
i! (tablero&u'&%' == 3) - 1$ es %alido< $1
tablero&u'&%' = i; 1$ anota el candidato $1
i! (i < ncuad) - 1$ llega al !inal del recorrido< $1
mo%er(tablero(i4.(u(%(*);
i! (=$*) tablero&u'&%' = 3; 1$ borra el candidato $1
0
else $* = .; 1$ hay solucion $1
0
0
;44;
0 >hile (=$* 55 ; < ,);
0

3ambiando el valor de N puede obtenerse una solución para un tablero cuadrado de
tama=o N.
& continuación" se muestra una adaptación del procedimiento !ue muestra todas las
soluciones. /i se e*ecuta para N 8 > se encuentra !ue ha$ @?A soluciones partiendo de
la es!uina superior iz!uierda.
3uando se encuentra una solución se llama a un procedimiento (no se ha codi#icado
a!u+) !ue imprime todo el tablero.
%oid mo%er(int tablero&'&"'(int i( int pos_)( int pos_y)
-
int ;( u( %;
!or (; = 3; ; < ,; ;44) -
u = pos_) 4 e+e)&;'; % = pos_y 4 e+ey&;';
i! (u = 3 55 u < " 55 % = 3 55 % < ") - 1$ esta dentro de los
limites $1
i! (tablero&u'&%' == 3) -
tablero&u'&%' = i;
i! (i < ncuad)
mo%er(tablero(i4.(u(%);
else imprimir_solucion(tablero);
tablero&u'&%' = 3;
0
0
0
0

El problema de las ocho reinas
3ontinuamos con problemas relacionados con el a*edrez. El problema !ue ahora se
plantea es claramente" como se verá" de vuelta atrás. /e recomienda intentar resolverlo
a mano.
/e trata de colocar ocho reinas sobre un tablero de a*edrez" de tal #orma !ue ninguna
amenace (pueda comerse) a otra. Para los !ue no sepan a*edrez deben saber !ue una
reina amenaza a otra pieza !ue est( en la misma columna" #ila o cual!uiera de las
cuatro diagonales.
La di#icultad !ue plantea este problema es la representación de los datos. /e puede
utilizar un arra$ bidimensional de tama=o B%B" pero las operaciones para encontrar una
reina !ue amenace a otra son algo engorrosas $ ha$ un truco para evitarlas. La solución
a!u+ e%puesta vuelve a ser tomada de 1irth (ver 2ibliogra#+a).
Es lógico !ue cada reina debe ir en una #ila distinta. Por tanto" en un arra$ se guarda la
posición de cada reina en la columna !ue se encuentre. E*emplo. si en la tercera #ila
ha$ una reina situada en la !uinta columna" entonces la tercera posición del arra$
guardará un >. & este arra$ se le llamará col.
Cace #alta otro arra$ !ue determine si ha$ puesta una reina en la #ila *7(sima. & este
arra$ se le llamará fila.
Por ltimo se utilizan dos arra$s más para determinar las diagonales libres" $ se
llamarán diagb $ diagc.
Para poner una reina se utiliza esta instrucción.
col&i' = + ; !ila&+' = diagb&i4+' = diagc&?4i-+' = @ABCD;
Para !uitar una reina esta otra.
!ila&+' = diagb&i4+' = diagc&?4i-+' = TEFD;
/e considera válida la posición para este caso.
i! (!ila&+' 55 diagb&i4+' 55 diagc&?4i-+') entonces proceder ...
& continuación se e%pone el código completo en 3. /e han utilizado tipos enumerados
para representar los valores booleanos.
#include <stdio.h
enum bool -@ABCD( TEFD0;
typede! enum bool boolean;
%oid ensayar(int i( boolean $*( int col&'( boolean !ila&'( boolean
diagb&'( boolean diagc&');
int main(%oid)
-
int i;
boolean *;
int col&,';
boolean !ila&,'(diagb&.#'( diagc&.#';
!or (i = 3; i < ,; i44) !ila&i' = TEFD;
!or (i = 3; i < .#; i44) diagb&i' = diagc&i' = TEFD;
ensayar(3(5*(col(!ila(diagb(diagc);
i! (*) -
print!(6:nColucion:6);
!or (i = 3; i < ,; i44) print!(6 7d6( col&i');
0 else print!(6:n"o hay solucion6);
return 3;
0
%oid ensayar(int i( boolean $*( int col&'( boolean !ila&'( boolean
diagb&'( boolean diagc&')
-
int +;
+ = 3;
$* = @ABCD;
do -
i! (!ila&+' 55 diagb&i4+' 55 diagc&?4i-+') -
col&i' = +; !ila&+' = diagb&i4+' = diagc&?4i-+' = @ABCD;
i! (i < ?) - 1$ encuentra solucion< $1
ensayar(i4.(*(col(!ila(diagb(diagc);
i! (=$*)
!ila&+' = diagb&i4+' = diagc&?4i-+' = TEFD;
0 else $* = TEFD; 1$ encuentra la solucion $1
0
+44;
0 >hile (=$* 55 + < ,);
0
Por ltimo" se de*a al lector !ue implemente un procedimiento !ue encuentre todas las
soluciones. /i se desea complicar más entonces se puede pedir !ue encuentre todas las
soluciones distintas" es decir" a!uellas !ue no sean rotaciones o inversiones de otras
soluciones.
&hora !ue se conoce el m(todo general" puede hacerse e%tensible a mltiples piezas
simultáneamente.

El Problema de la mochila (selección óptima)
3on anterioridad se ha estudiado la posibilidad de encontrar una nica solución a un
problema $ la posibilidad de encontrarlas todas. Pues bien" ahora se trata de encontrar
la me*or solución" la solución óptima" de entre todas las soluciones.
Partiendo del es!uema !ue genera todas las soluciones e%puesto anteriormente se
puede obtener la me*or solución (la solución óptima" seleccionada entre todas las
soluciones) si se modi#ica la instrucción almacenar_solucion por esta otra.
si !(solucion) !(optimo) entonces optimo <- solucion
siendo f(s) #unción positiva" optimo es la me*or solucion encontrada hasta el momento"
$ solucion es una solucion !ue se está probando.
El problema de la mochila consiste en llenar una mochila con una serie de ob*etos !ue
tienen una serie de pesos con un valor asociado. Es decir" se dispone de n tipos de
ob*etos $ !ue no ha$ un nmero limitado de cada tipo de ob*eto (si #uera limitado no
cambia mucho el problema). 3ada tipo i de ob*eto tiene un peso wi positivo $ un valor vi
positivo asociados. La mochila tiene una capacidad de peso igual a W. /e trata de llenar
la mochila de tal manera !ue se maximice el valor de los ob*etos incluidos pero
respetando al mismo tiempo la restricción de capacidad. Notar !ue no es obligatorio !ue
una solución óptima llegue al l+mite de capacidad de la mochila.
Ejemplo: se supondrá.
n 8 A
1 8 B
5() 8 :" @" A" >
v() 8 @" >" D" ;?
Es decir" ha$ A tipos de ob*etos $ la mochila tiene una capacidad de B. Los pesos var+an
entre : $ >" $ los valores relacionados var+an entre @ $ ;?.
6na solución no óptima de valor ;: se obtiene introduciendo cuatro ob*etos de peso :" o
: de peso A. Etra solución no óptima de valor ;@ se obtiene introduciendo : ob*etos de
peso @ $ ; ob*eto de peso :. '3uál es la solución óptima).
& continuación se muestra una solución al problema" variante del es!uema para obtener
todas las soluciones.
%oid mochila(int i( int r( int solucion( int $optimo)
-
int ;;
!or (; = i; ; < n; ;44) -
i! (peso&;' <= r) -
mochila(;( r - peso&;'( solucion 4 %alor&;'( optimo);
i! (solucion 4 %alor&;' $optimo) $optimo = solucion4%alor&;';
0
0
0
Ficho procedimiento puede ser e*ecutado de esta manera" siendo n" G" peso $ %alor
variables globales para simpli#icar el programa.
n = H(
G = ,(
peso&' = -/(8(H(#0(
%alor&' = -8(#(I(.30(
optimo = 3;
...
mochila(3( G( 3( 5optimo);

Ebservar !ue la solución óptima se obtiene independientemente de la #orma en !ue se
ordenen los ob*etos.

Problemas propuestos
- Caminos. EIE GH.
Enunciado 7 /olución
7 Tom !err "solamente el apartado #$. EIE GH.
Enunciado
- Buque. EIE GB.
Enunciado
- %ellos "El correo del &ar$. EIE GG.
Enunciado
- El salto del caballo. EIE :??;.
Enunciado
- 'slas en el mar. IEI G:.
Enunciado (en ingl(s. Islands in the sea)
- ()meros primos. IEI GA.
Enunciado (en ingl(s. 0he Primes) 7 /olución
7 *uc+os otros problemas requieren vuelta atr,s- en general se trata de
algoritmos auxiliares para resolver una peque.a tarea.
- 0ambi(n los algoritmos de vuelta atrás permiten la resolución del problema del
laberinto" puesto !ue la vuelta atrás no es más !ue el recorrido sobre un gra#o
impl+cito #inito o in#inito. Fe todas #ormas" los problemas de laberintos se resuelven
mucho me*or mediante e%ploración en anchura (ver gra#os).