Vous êtes sur la page 1sur 6

lema de las 8 reinas

Este problema consiste en determinar si se pueden colocar 8 damas en un tablero de


ajedrez de 64 casillas, de tal manera que no queden amenazadas.
Si furamos a resolver este problema con fuerza bruta, tendramos que analizar todas
las ubicaciones posibles de 8 reinas en el tablero hasta que nos encontremos con una
combinacin en la que ninguna reina est amenazada o hayamos realizado todas las
ubicaciones posibles.
Para la colocacin de la primera dama hay 64 casillas disponibles. Cuando colocamos
sta, quedaran 63 casillas posibles para la segunda dama. Y as sucesiva y
recursivamente hasta que llegaramos a un total de combinaciones posibles de 64 *
63 * 62 * 61* 60 * 59 * 58 * 57, para un total de 200 000 millones de combinaciones.
Una computadora muy rpida trabajando da y noche demorara ms de medio ao
solamente para obtener todas las combinaciones, eso sin analizarlas. Por lo que
evidentemente esta es una solucin muy costosa y puede mejorarse como se ver a
continuacin.
Sabemos que si podemos ubicar 8 reinas sin que se amenacen, entonces solo puede
haber una reina por columna, ya que dos reinas en una misma columna estaran
amenazndose. Por tanto el algoritmo de este problema consiste en:
1 Si n es cero, entonces ya no quedan reinas por poner y el problema tiene solucin.
2 Se intenta ubicar una reina en cada columna de izquierda a derecha.
3 Se intenta colocar la reina en cada celda de la columna y se verifica si desde esta
posicin se amenaza a las reinas ubicadas en las columnas a la izquierda. Si no se
amenazan las reinas anteriores, entonces trataremos de colocar las reinas restantes en
las columnas de la derecha (aproximacin recursiva al caso base).
4 Si ninguna celda de la columna satisface el paso 3, no se puede ubicar una reina en
la columna y se vuelve atrs para intentar ubicar en otra posicin a la reina ubicada en
la columna anterior. Si estamos en la primera columna, entonces el problema no tiene
solucin.

ubicareinas1 Backtracking. Problema del laberinto


Este mtodo lo nico que hace es verificar si se ha recibido un tablero correcto (es
cuadrado y tiene todas las celdas en false). Luego llama al mtodo privado UbicaReinas
que es el que intenta ubicar k reinas a partir del ancho del tablero.

ubicareinas2 Backtracking. Problema del laberinto


El mtodo Amenaza sera el encargado de verificar si se amenaza alguna otra dama,
recorriendo el array de forma vertical, horizontal y diagonal, a partir de la posicin
[i , j]. Adems de implementar este mtodo como ejercicio, puede mejorar un poco
ms el algoritmo. Fjese que dos reinas no pueden ubicarse en la misma fila.
Buscar la salida en un laberinto
Al menos para mi este problema es el ideal para demostrar el poder del backtracking.
Se trata de encontrar la salida dentro de un laberinto. La estrategia a seguir para salir
de un laberinto es primeramente, explorar hacia delante un posible camino y ver si
conduce a una solucin. Si no conduce a una solucin, hay que desandar el camino y
volver atrs para intentar con otro.

Considere un laberinto representado por un array rectangular (bidimensional) de bool,


en el que una celda con valor false significa que hay un obstculo por el que no se
puede atravesar. Y una celda con valor true es una celda por la que se puede pasar.
El problema consiste por ejemplo en suponer que entramos por la celda en la posicin
0,0 y se quiere encontrar en camino hasta la posicin m,n donde m es la cantidad de
filas del array y n la cantidad de columnas. Puede resolverse de igual forma si se
empieza y se termina por otras celdas.
El mtodo C# HaySalida es el siguiente:

haysalida Backtracking. Problema del laberinto


Como se ha visto en los ejemplos anteriores, este primer mtodo es el que se encarga
de llamar al otro mtodo privado y recursivo de igual nombre. Veamos ahora el cdigo
y luego lo comentamos.

haysalida2 Backtracking. Problema del laberinto

Empezamos desde la lnea 2 donde se indica el caso base de la recursividad. O sea, si


se ha llegado a la celda de salida y esta es true. Despus comprobamos si estamos en
una celda por la cual no se puede pasar, en caso de que no se pueda pasar retornamos
false. Si se puede pasar por esa casilla, la ponemos en false para garantizar que no
pasaremos de nuevo por ella en caso que el camino no conduzca a una salida.
Luego, en las prximas llamadas recursivas se intenta averiguar si hay salida desde las
casillas vecinas y se retorna true en caso de encontrar la salida. Si se llega a la ltima
lnea es porque desde ninguna de las celdas vecinas hay salida, y por tanto no hay
salida desde la celda actual, por lo que se retorna false.
El mtodo HaySalida solamente nos dice si existe o no salida del laberinto, pero no nos
da la respuesta de cual es la salida, o sea, el camino a seguir para llegar a la salida.
Intenta hacer un mtodo SalidaLaberinto que devuelva un array con los puntos por los
que se debe pasar para llegar a la salida mas corta.
En este caso para estar seguros de encontrar el camino ms corto, habra que explorar
todos los caminos posibles y compararlos. Note que en el mtodo HaySalida, primero
se explora el camino que va en direccin diagonal y luego los caminos ms cercanos a
esta, lo cual no quiere decir que se encuentre el camino ms corto. Esto es lo que se
conoce como heurstica, que consiste en mejorar los algoritmos basados en la
experiencia, el conocimiento y el sentido comn.
Solo agregar que esta tcnica de backtracking o Vuelta Atrs, es muy utilizada en
juegos, ya que ante una determinada situacin del juego se exploran los diferentes
caminos a seguir segn las posibles jugadas del contrario y as sucesivamente,
decidiendo las jugadas, hasta que se conduce a la victoria.
Bueno, hasta aqu este pequeo tutorial de recursividad en C#. Seguro faltaron
muchas cosas por tratar en este tema, ya que no soy un experto ni mucho menos.
Para aprender recursividad lo ms importante es practicar, leer y copiar cdigo. Aqu
dejo algunos ejercicios. Si quieres luego debatimos las soluciones.
1- Escriba un mtodo recursivo string Invierte (string s) que devuelva el reverso de la
cadena s.
2- Implemente un mtodo que demuestre que con un caballo se pueden recorrer
todas las casillas de un tablero de ajedrez sin pasar dos veces por una misma casilla.
3- Escriba el mtodo static long Factorial(int n) que devuelva el factorial del nmero n.
0! = 1, y para n 1, n! = n * (n 1)!
4- Escriba el mtodo static bool EsPalndromo(string s) que diga si el string s es
palndromo. Un string es palndromo si se lee de la misma forma de izquierda a
derecha que de derecha a izquierda.

5- Implemente el mtodo static void DescomposicionSumandos(int n) que muestre en


la pantalla todas las formas posibles de descomponer el nmero n en sumandos. Por
ejemplo, para n=5, en la pantalla se muestra:
11111
1112
122
113
14
23
5
6- El Taxista: Un taxista se desplaza en su taxi por una ciudad en la cual slo est
permitido conducir hacia el ESTE y hacia el SUR.
Implemente el mtodo static int CantidadCaminos(int xOrig, int yOrig, int xDest, int
yDest) que devuelva la cantidad de caminos diferentes por los que se puede llegar
desde el punto (xOrig, yOrig) hasta el punto (xDest, yDest). Asuma que xDest xOrig y
que yDest yOrig.

Vous aimerez peut-être aussi