Está en la página 1de 25

Backtracking

Algoritmo de vuelta atrás


Intro – fuerza bruta
• En programación dinámica – optimización
• En backtracking es cuando tenemos varias soluciones
Ejemplo…
State space tree

**restricciones
DFS
Backtracking
• Se utiliza para resolver problemas en los que se selecciona una
secuencia de objetos de un conjunto específico para que la secuencia
satisfaga algún criterio.
• Un caso de uso es el de encontrar la
salida de un laberinto. Intentar ir en
una dirección, y si llegamos a un
callejón sin salida, regresamos a la
última intersección y probamos una
dirección diferente. En el peor de los
casos, terminamos probando todos los
pasajes posibles del laberinto.
• Backtracking es una búsqueda en
profundidad modificada de un árbol.
• Un recorrido de árbol de preorden es
una búsqueda en profundidad de un
árbol (depth-first search). Esto
significa que la raíz se visita primero,
y una visita a un nodo es seguida
inmediatamente por visitas a todos
los descendientes del nodo. Una
búsqueda en profundidad no
requiere que los hijos sean visitados
en ningún orden en particular, pero
visitaremos a los hijos de un nodo de
izquierda a derecha.
Recordando los Recorridos
Recorrer el árbol es “pasar por” o “visitar” todos los nodos del mismo.

Recorridos típicos:
✔ Preorden
✔ Inorden
✔ Postorden

Otro tipo de recorridos


✔ Conversos
✔ Nivel por nivel
Recorrido preorden
Proceso:
✔ Visita el nodo raíz del árbol.
✔ Recorre el preorden el subárbol izquierdo del nodo raíz.
✔ Recorre el preorden el subárbol derecho del nodo raíz.
21

Aplicación: Generar una réplica del árbol. 13 33

10 18 25 40

Recorrido en Preorden
21, 13, 10, 18, 33, 25, 40
Implementación en preorden
void preorden(Nodo r) Implementación
{ if ( r != NULL) del Preorden para
desplegar el
{ cout << r.getData(); contenido del
preorden (r.getLeft()); árbol.
preorden (r.getRight());
Llamada a la
} función:
} preorden(root);
Ejemplo

12

7 21
Recorrido en Preorden
12, 7, 4, 2, 9, 8, 11, 21, 16, 19, 25
4 25
9 16

2
8 11 19
Otro ejemplo:

#
8 Recorrido en Preorden
@
#, @, 2, $, 8, A, 5, %
A %
2

$ 5
Backtracking funciona para
Búsqueda de profundidad todos los árboles, no
necesariamente binarios
Árbol del espacio de estados (state space tree)
Backtracking es una mejora de la búsqueda exhaustiva (buscar en todo
el árbol), la solución se construye paso a paso, en donde cada paso
analiza los posibles valores que pueda tomar una variable.
Utiliza una estructura de árbol, cuya raíz es el inicio del problema y
cada nivel está formado por los posibles valores que puede tomar una
de las variables involucradas en el problema. Esto significa que el
último nivel del árbol contiene todas las posibles soluciones del
espacio, por tal razón a este árbol se le conoce como “Árbol del
espacio de estados”.
Nodo promisorio
Backtracking no forma el árbol desde el inicio, lo va formando usando DFS.
Los nodos interiores del árbol tienen soluciones parciales al problema y las hojas contienen
soluciones completas al problema.
Al explorar un nodo se verifica que la solución parcial hasta ese momento cumpla con las
condiciones de una posible solución, si es así este nodo es clasificado como “promisorio”,
por lo que se expande y se continúa el proceso de “primero en profundidad”. Si, por el
contrario, se encuentra que la solución parcial obtenida hasta ese momento no cumple con
las condiciones para ser una solución al problema, ese nodo se clasifica como “no
promisorio”, por lo que se desecha, se regresa a su padre, es decir, se hace backtracking y
se continúa el proceso con sus hermanos. En el caso que ya no haya más nodos por
analizar se hace backtracking un nivel más arriba y así sucesivamente.
Algoritmo
Problema de las damas de ajedrez
• El objetivo de este problema es colocar n reinas en un tablero de ajedrez
de n x n para que no haya dos reinas que se amenacen entre sí.
• El criterio es que no puede haber dos reinas en la misma fila, columna o
diagonal.
• La secuencia del problema son las n posiciones en las que se colocan las
reinas.
• El conjunto para cada elección es 𝑛𝑛2 posiciones posibles en el tablero de
ajedrez, y el criterio es que no hay dos reinas que puedan amenazarse
entre sí.
• El problema de las n-reinas es una generalización de su instancia cuando n
= 8, que es la instancia que usa un tablero de ajedrez estándar.
Problema de n-Reynas cuando n = 4
• Objetivo: colocar cuatro reinas en un tablero de ajedrez de 4 x 4 para que
no haya dos reinas que se amenacen entre sí.
• Criterio: No pueden haber dos reinas en la misma fila, columna o diagonal.
• Las reinas pueden moverse horizontal, vertical o diagonalmente a cualquier
distancia.
• La secuencia a encontrar son las N posiciones2
para las reinas y el conjunto
del que se eligen esas posiciones son las 𝑛𝑛 posiciones posibles en el
tablero, el criterio que debe cumplir la secuencia es que ninguna de las
reinas pueda atacar a otra.
• La instancia se puede resolver asignando a cada reina una fila diferente y
verificando qué combinaciones de columnas dan soluciones.
• En este caso, hay 4 x 4 x 4 x 4 = 256 soluciones candidatas.
Solución candidata
• Un camino desde la raíz hasta la hoja es una solución candidata.
• Este árbol se llama árbol de estado de espacio (state space tree). Una
simple búsqueda en profundidad de un árbol de estado de espacio es
como seguir cada camino en un laberinto hasta llegar a un callejón sin
salida. No aprovecha ninguna señal en el camino. Podemos hacer la
búsqueda más eficiente buscando estas coincidencias.
• Recordemos que llamamos a un nodo no prometedor si podemos
determinar que no puede conducir a una solución. Si existe la
posibilidad de que se pueda encontrar una solución, llamamos al
nodo prometedor.
Conceptos
• El backtracking consiste en realizar una búsqueda en profundidad de
un árbol de estado, comprobar si cada nodo es prometedor y, si no lo
es, retroceder hasta el padre del nodo. Este proceso se llama poda.
Un subárbol que consta de los nodos visitados se denomina árbol de
estado podado (pruned state space tree).
Objetivo de la función: verificar si dos reinas
están en la misma columna o diagonal.
1.- Construir un árbol en el que las opciones de columna para la primera reina (en la fila 1) se
almacenan en los nodos de nivel 1 en el árbol, las opciones de columna para la segunda reina están
en los nodos de nivel 2, y así sucesivamente.
Visualizar un modelo de árbol para el espacio de solución. Podemos simplificar nuestro árbol
reconociendo que no pueden haber dos reinas en la misma fila.
Entonces, los hijos de la raíz mostrarán la posición de la reina en la fila 1.
Para una tabla de tamaño n x n, habrá n hijos de la raíz.
2.- Idear formas de eliminar las ramas antes de atravesarlas.
En el problema de las n-reinas, una forma de eliminar una rama es poner dos reinas en la misma
columna. Otra forma de eliminar ramas es reconocer que no pueden haber dos reinas en la misma
diagonal. Entonces, si elegimos [1, 1] para la reina en la fila 1, entonces no necesitamos evaluar [2,
2] para la reina en la fila 2.
Usando estas dos reglas, podemos reducir el espacio de la solución . Cuando identificamos un nodo
como no prometedor, volvemos al padre y probamos con otra rama. Eventualmente llegaremos a
uno o más nodos hoja y tendremos varias secuencias candidatas para evaluar.
En el problema de las n-reinas, si llegamos a cualquier nodo hoja, tenemos nuestra solución.
Esta figura muestra una parte del árbol de estado para la instancia del
problema de las n reinas en donde n = 4. El par ordenado <i,j> de cada
nodo significa que la reina del iésimo renglón está en la columna j.
Cada ruta de la raíz a la hoja es una solución candidata
Aquí se ve que si ponemos a la primer reina en la columna 1, la
segunda no se puede poner en la columna 1 (a) o en la columna 2 (b).
Esta figura muestra una parte del árbol de estado para la instancia del
problema de las n reinas en donde n = 4. Solo se muestran los nodos
que se revisaron para la primer solución. Esa solución es el nodo
sombreado <4,3>. Cada nodo no prometedor se marca con una cruz.

Primer solución
• Estas son las posiciones que se intentaron cuando se hizo el
backtracking para n=4. Cada posición no prometedora esta marcada
con X
Hasta este punto ya encontramos la primer solución (nodo
sombreado).

Ojo, el algoritmo de backtracking no requiere realmente crear el árbol.


Solo se ocupa tener control de los valores en la rama que se está
investigando. Esta es la forma en la que se implementa el algoritmo.

El árbol de estado existe implícitamente en el algoritmo debido a que


no se construye.

También podría gustarte