Вы находитесь на странице: 1из 23

ALGORITMICA III

Laboratorio de Algoritmos de Retroceso

Docente: Carlos A. Ruiz De La Cruz Melo Correo: zorroculto69@hotmail.com

LAS n REINAS
Un problema clsico que puede ser resuelto con un diseo Vuelta Atrs es el denominado de las ocho reinas y en general, de las n reinas. Disponemos de un tablero de ajedrez de tamao 8x8, y se trata de colocar en l ocho reinas de manera que no se amenacen segn las normas del ajedrez, es decir, que no se encuentren dos reinas ni en la misma fila, ni en la misma columna, ni en la misma diagonal

LAS n REINAS
Cualquier solucin a este problema estar representada por una 8-tupla [x1,x2, x3 , x4 , x5, x6, x7, x8 ] en la que cada xI representa la columna donde la reina de la fila i-sima es colocada. R

[ 4, 6, 8, 2, 7, 1, 3, 5 ]
R

R R
R R R

Posible solucin

LAS n REINAS
RESTRICCIONES
Para decidir en cada etapa cules son los valores que puede tomar cada uno de los elementos xi hemos de tener en cuenta lo que hemos denominado restricciones a fin de que el nmero de opciones en cada etapa sea el menor posible. En los algoritmos Vuelta Atrs podemos diferenciar dos tipos de restricciones:

1. Restricciones explcitas. Formadas por reglas que restringen los valores que pueden tomar los elementos xi a un conjunto determinado. En nuestro problema este conjunto es S={1,2,3,4,5,6,7,8}.

LAS n REINAS
RESTRICCIONES
2. Restricciones implcitas. Indican la relacin existente entre los posibles valores de los xi para que stos puedan formar parte de una n-tupla solucin. En el problema que nos ocupa podemos definir dos restricciones implcitas.
En primer lugar sabemos que dos reinas no pueden situarse en la misma columna y por tanto no puede haber dos xi iguales (obsrvese adems que la propia definicin de la tupla impide situar a dos reinas en la misma fila, con lo cual tenemos cubiertos los dos casos, el de las filas y el de las columnas). Por otro lado sabemos que dos reinas no pueden estar en la misma diagonal, lo cual reduce el nmero de opciones. Esta condicin se refleja en la segunda restriccin implicita que, en forma de ecuacin, puede ser expresada como |x x| |y y|, siendo (x,y) y (x,y) las coordenadas de dos reinas en el tablero.

ARBOL DE EXPANSION
[1, 2, -, -]2
[1, -, -, -]1 [1, 3, -, -]3 [1, 3, 2, -]4 [1, 3, 4, -]5 [1, 4, 2, -]7

[1, 4, 2,3]8

[-, -, -, -] 0
[2, -, -, -]10

[1, 4, -, -]6
[2, 1, -, -]11

[1, 4, 3, -]9

[2, 3, -, -]12
[2, 4, -, -]13 [ 2,4,1, -]13

[2, 4, 1, 3]15

ARBOL DE EXPANSION

Configuracin final

8 REINAS

EL RECORRIDO DEL CABALLO


Se dispone de un tablero rectangular, por ejemplo el tablero de ajedrez, y de un caballo, que se mueve segn las reglas de este juego. El objetivo es encontrar una manera de recorrer todo el tablero partiendo de una casilla determinada, de tal forma que el caballo pase una sola vez por cada casilla. Una variante es obligar al caballo a volver a la posicin de partida en el ltimo movimiento.

Por ltimo se estudiar como encontrar todas las soluciones posibles partiendo de una misma casilla.

EL RECORRIDO DEL CABALLO


Para resolver el problema hay que realizar todos los movimientos posibles hasta que ya no se pueda avanzar, en cuyo caso hay que dar marcha atrs, o bien hasta que se cubra el tablero. Adems, es necesario determinar la organizacin de los datos para implementar el algoritmo.

EL RECORRIDO DEL CABALLO


Con las coordenadas en las que se encuentre el caballo y las ocho coordenadas relativas se determina el siguiente movimiento. Las coordenas relativas se guardan en dos arrays:

ejex = [2, 1, -1, -2, -2, -1, 1, 2] ejey = [1, 2, 2, 1, -1, -2, -2, -1]

EL RECORRIDO DEL CABALLO


Cuando se encuentra una solucin, una variable que se pasa por referencia es puesta a 1 (cierto). Para codificar el programa, es necesario considerar algunos aspectos ms, entre otras cosas no salirse de los lmites del tablero y no pisar una casilla ya cubierta (seleccin del candidato).
1 38 59 36 43 48 57 52 60 35 2 49 58 51 44 47 39 32 37 42 3 46 53 56 34 61 40 27 50 55 4 45 31 10 33 62 41 26 23 54 18 63 28 11 24 21 14 5 9 30 19 16 7 12 25 22 64 17 8 29 20 15 6 13

Se determina que hay solucin cuando ya no hay ms casillas que recorrer.

EL RECORRIDO DEL CABALLO


A continuacin se expone un cdigo completo en C, que recubre un tablero cuadrado de lado N partiendo de la posicin (0,0).

#include<stdio.h> #include "conio.h" #define N 8 #define ncuad N*N void mover(int tablero[][N],int i,int pos_x,int pos_y,int *q); int ejex[8]={2,1,-1,-2,-2,-1,1,2}; int ejey[8]={1,2, 2, 1,-1,-2,-2,-1};

EL RECORRIDO DEL CABALLO


int main(void){ int tablero[N][N];/*tablero de ajedrez*/ int i,j,q; /*inicializa el tablero a cero*/ for(i=0;i<N;i++) for(j=0;j<N;j++) tablero[i][j]=0; /*pone el primer movimiento*/ tablero[0][0]=1; mover(tablero,2,0,0,&q); if(q) { for(i=0;i<N;i++){ for(j=0;j<N;j++) printf("%3d ",tablero[i][j]); putchar('\n'); } } else printf("\nno existe solucion\n"); getch(); }

EL RECORRIDO DEL CABALLO


void mover(int tablero[][N],int i,int pos_x,int pos_y,int *q){ int k,u,v; k=0; *q=0; do{ u=pos_x+ejex[k]; v=pos_y+ejey[k];/*seleccionar candidato*/ if(u>=0 && u<N && v>=0 && v<N){ /*esta dentro de los limites*/ if(tablero[u][v]==0){/*es valido?*/ tablero[u][v]=i; if(i<ncuad) { /*llega al final del recorrido*/ mover(tablero,i+1,u,v,q); if(!*q) tablero[u][v]=0; } else *q=1;/*hay solucion*/ } } k++; }while(!*q && k<8); } CABALLO

EL RECORRIDO DEL LABERINTO


Definicin del problema
Conceptualizacin: El problema se ubica en un contexto en el que se debe buscar una solucin a un laberinto con una entrada y una salida, y con movimientos vlidos en cuatro direcciones (no diagonales). En el caso de este ejemplo, el contexto est limitado a una aplicacin, en la que el laberinto est representado mediante una matriz de nmeros enteros.

Objetivo: Partiendo de la entrada del laberinto, sealar una ruta que nos gue hasta la salida.

EL RECORRIDO DEL LABERINTO

Por ejemplo, dado el siguiente laberinto:

Una solucin que nos permitira alcanzar nuestro objetivo sera la ruta mostrada con asteriscos en la siguiente figura:

EL RECORRIDO DEL LABERINTO


Descripcin general de la solucin
La solucin se basa en una tarea o funcin que se llamar recursivamente para intentar solucionar el laberinto a partir de una posicin particular. Desde cualquier lugar dentro del laberinto se intentar resolverlo primero intentando hacia izquierda, luego a la derecha, luego arriba y finalmente abajo. Para hacer estos intentos se emplear la funcin recursiva. El procedimiento parte de la posicin de entrada. Se utilizarn marcas que sern dejadas en el camino para no intentar por caminos por los que ya se pas y, en particular, no volver atrs salvo si se determina que no hay solucin por el camino que se sigue hasta ahora.

EL RECORRIDO DEL LABERINTO


Conceptualizacin de la solucin Variables:
La posicin de la entrada en el laberinto estar dada por las coordenadas dentro de la matriz, representadas por las variables x0, y0, para la fila y la columna, respectivamente. De manera similar, la posicin de la salida del laberinto se guardar en xf, yf . Cada posicin de la matriz puede estar en uno de tres estados: parte del muro (ladrillo) camino libre no visitado camino libre visitado

EL RECORRIDO DEL LABERINTO


int { { { { { { { { { { { { { { lab[FILAS][COLUMNAS] L, L, L, L, L, L, L, E, E, E, L, E, L, E, L, L, E, L, E, E, E, L, E, E, E, E, L, E, L, E, L, L, L, L, E, L, E, E, E, L, E, E, L, E, L, L, L, L, L, L, E, E, E, E, E, E, L, L, L, L, L, L, L, L, E, E, E, E, E, E, L, E, L, L, L, L, L, L, E, E, L, E, E, E, L, L, L, L, L, L, L, = L, L, L, L, L, L, L, E, L, E, E, E, L, L, E, E, L, E, E, E, E, L, L, E, L, L, L, L, E, L, L, L, L, E, L, E, E, E, L, L, E, E, E, E, E, E, E, L, E, L, E, L, L, E, L, L, L, L, L, E, E, E, L, L, L, L, E, E, E, E, E, L, L, L, L, L, E, L, L, L, L, L, L, E, E, E, E, L, E, E, L, L, E, E, E, L, E, L, L, L, L, L, E, L, L, E, L, L, L, E, E, E, E, L, E, E, L, L, E, E, L, E, E, E, L, E, L, E, L, L, L, E, E, E, E, L, E, L, L, L, E, L, L, L, E, L, L, L, L, E, E, E, E, E, L, L, L, E, E, E, E, E, E, L, L, L, E, E, L, L L L L L L L L L L L E L }, }, }, }, }, }, }, }, }, }, }, }, } };

La inicializacin de la matriz que aqu se muestra corresponde al laberinto presentado en la figura del inicio.

Los caminos estn formados de espacios libres (E's). Observe el contorno del laberinto, formado por L's, y los puntos de entrada y salida.

EL RECORRIDO DEL LABERINTO


Descripcin:
Esta funcin analiza una posicin dentro del laberinto, especificada por la fila y columna recibidas como parmetro, y deduce si es una posicin vlida para recorrer. Bsicamente debe verificar que no est fuera de los lmites del laberinto, que no se trate de una posicin en la que hay pared, y que no se trate de una posicin previamente visitada.
int valida(int f, int c) { int resultado = TRUE; /* Se supone inicialmente valida */ /* Controla si la posicion esta fuera del laberinto */ if ((f<0) || (f>=FILAS) || (c<0) || (c>=COLUMNAS)) resultado = FALSE; /* Controla si la posicion ya fue visitada o es muro */ if (lab[f][c] == MARCA || lab[f][c] == L) resultado = FALSE; return(resultado); }

EL RECORRIDO DEL LABERINTO


Descripcin:
Tarea recursiva que recorre el laberinto a partir de una posicin dada por la fila y columna pasadas como parmetro y devuelve un valor booleano que indica si se logro llegar a la salida.
int recorrer(int fil, int col) { int listo = FALSE; /* Indica si se ha encontrado la salida */ /* Se marca la casilla como visitada */ lab[fil][col] = MARCA; /* Se controla la condicion de termino de recursividad: */ /* " Llegamos a la salida? " */ if (fil == xf && col == yf) return(TRUE); if (!listo && valida(fil,col-1)) /* Intento a la izquierda */ listo = recorre(fil,col-1); if (!listo && valida(fil,col+1)) /* Intento a la derecha */ listo = recorre(fil,col+1); if (!listo && valida(fil-1,col)) /* Intento hacia arriba */ listo = recorre(fil-1,col); if (!listo && valida(fil+1,col)) /* Intento hacia abajo */ listo = recorre(fil+1,col); /* Si no se logro resolver el laberinto desde esta posicion, se */ /* desmarca la casilla pues no sera parte de la solucion. En este */ /* caso se retornara falso lo que provocara que se retroceda. */ if (!listo) lab[fil][col] = E; /* Se retorna TRUE/FALSE dependiendo de si se encontro solucion */ return(listo);

EL RECORRIDO DEL LABERINTO


El caso base de la recursividad (condicin de termino) es que las coordenadas correspondan con la salida del laberinto. En caso contrario, se procede a marcar la casilla y a intentar en las distintas direcciones (izquierda, derecha, arriba y abajo), asegurndose primero que en esa direccin haya una casilla valida (no ladrillo, no fuera del laberinto y no visitada). En caso en que ninguna direccin nos lleva a la salida, se desmarca la casilla actual (pues se va a retroceder) y se devuelve falso como valor de retorno. Las marcas sirven tambin para sealar la ruta que conforma la solucin, una vez alcanzada.
int recorrer(int fil, int col) { int listo = FALSE; /* Indica si se ha encontrado la salida */ /* Se marca la casilla como visitada */ lab[fil][col] = MARCA; /* Se controla la condicion de termino de recursividad: */ /* " Llegamos a la salida? " */ if (fil == xf && col == yf) return(TRUE); if (!listo && valida(fil,col-1)) /* Intento a la izquierda */ listo = recorre(fil,col-1); if (!listo && valida(fil,col+1)) /* Intento a la derecha */ listo = recorre(fil,col+1); if (!listo && valida(fil-1,col)) /* Intento hacia arriba */ listo = recorre(fil-1,col); if (!listo && valida(fil+1,col)) /* Intento hacia abajo */ listo = recorre(fil+1,col); /* Si no se logro resolver el laberinto desde esta posicion, se */ /* desmarca la casilla pues no sera parte de la solucion. En este */ /* caso se retornara falso lo que provocara que se retroceda. */ if (!listo) lab[fil][col] = E; /* Se retorna TRUE/FALSE dependiendo de si se encontro solucion */ return(listo);

LABERINTO

EL RECORRIDO DEL REY


Dado un tablero de ajedrez de tamao nxn, un rey es colocado en una casilla arbitraria de coordenadas (x,y). El problema consiste en determinar los n 21 movimientos de la figura de forma que todas las casillas del tablero sean visitadas una sola vez, si tal secuencia de movimientos existe.

Вам также может понравиться