Algoritmo Prim

21
// Declaraciones en el archivo .h const int INF = 1000000; int cn; //cantidad de nodos vector< vector<int> > ady; //matriz de adyacencia // Devuelve la matriz de adyacencia del arbol minimo. vector< vector<int> > Grafo :: prim(){ // uso una copia de ady porque necesito eliminar columnas vector< vector<int> > adyacencia = this->ady; vector< vector<int> > arbol(cn); vector<int> markedLines; vector<int> :: iterator itVec; // Inicializo las distancias del arbol en INF. for(int i = 0; i < cn; i++) arbol[i] = vector<int> (cn, INF); int padre = 0; int hijo = 0; while(markedLines.size() + 1 < cn){ padre = hijo; // Marco la fila y elimino la columna del nodo padre. markedLines.push_back(padre); for(int i = 0; i < cn; i++) adyacencia[i][padre] = INF; // Encuentro la menor distancia entre las filas marcadas. // El nodo padre es la linea marcada y el nodo hijo es la columna del minimo. int min = INF; for(itVec = markedLines.begin(); itVec != markedLines.end(); itVec++) for(int i = 0; i < cn; i++) if(min > adyacencia[*itVec][i]){ min = adyacencia[*itVec][i]; padre = *itVec; hijo = i; } arbol[padre][hijo] = min; arbol[hijo][padre] = min; } return arbol; } Código en JAVA

Transcript of Algoritmo Prim

Page 1: Algoritmo Prim

// Declaraciones en el archivo .h

const int INF = 1000000;

int cn; //cantidad de nodos

vector< vector<int> > ady; //matriz de adyacencia

// Devuelve la matriz de adyacencia del arbol minimo.

vector< vector<int> > Grafo :: prim(){

// uso una copia de ady porque necesito eliminar columnas

vector< vector<int> > adyacencia = this->ady;

vector< vector<int> > arbol(cn);

vector<int> markedLines;

vector<int> :: iterator itVec;

// Inicializo las distancias del arbol en INF.

for(int i = 0; i < cn; i++)

arbol[i] = vector<int> (cn, INF);

int padre = 0;

int hijo = 0;

while(markedLines.size() + 1 < cn){

padre = hijo;

// Marco la fila y elimino la columna del nodo padre.

markedLines.push_back(padre);

for(int i = 0; i < cn; i++)

adyacencia[i][padre] = INF;

// Encuentro la menor distancia entre las filas marcadas.

// El nodo padre es la linea marcada y el nodo hijo es la

columna del minimo.

int min = INF;

for(itVec = markedLines.begin(); itVec != markedLines.end();

itVec++)

for(int i = 0; i < cn; i++)

if(min > adyacencia[*itVec][i]){

min = adyacencia[*itVec][i];

padre = *itVec;

hijo = i;

}

arbol[padre][hijo] = min;

arbol[hijo][padre] = min;

}

return arbol;

}

Código en JAVA

Page 2: Algoritmo Prim

public class Algorithms{ public static Graph PrimsAlgorithm (Graph g, int s) { int n = g.getNumberOfVertices (); Entry[] table = new Entry [n]; for (int v = 0; v < n; ++v) table [v] = new Entry (); table [s].distance = 0; PriorityQueue queue = new BinaryHeap (g.getNumberOfEdges()); queue.enqueue ( new Association (new Int (0), g.getVertex (s))); while (!queue.isEmpty ()) { Association assoc = (Association) queue.dequeueMin(); Vertex v0 = (Vertex) assoc.getValue (); int n0 = v0.getNumber (); if (!table [n0].known) { table [n0].known = true; Enumeration p = v0.getEmanatingEdges (); while (p.hasMoreElements ()) { Edge edge = (Edge) p.nextElement (); Vertex v1 = edge.getMate (v0); int n1 = v1.getNumber (); Int wt = (Int) edge.getWeight (); int d = wt.intValue (); if (!table[n1].known && table[n1].distance>d) { table [n1].distance = d; table [n1].predecessor = n0; queue.enqueue ( new Association (new Int (d), v1)); } } } } Graph result = new GraphAsLists (n); for (int v = 0; v < n; ++v) result.addVertex (v);

Page 3: Algoritmo Prim

for (int v = 0; v < n; ++v) if (v != s) result.addEdge (v, table [v].predecessor); return result; }}

Problema de las ocho reinas

Movimientos posibles de una reina en un tablero de 4x4.

Una posible solución entre muchas en un tablero de 8x8

El problema de las ocho reinas se trata de un acertijo en el que se colocan ocho reinas sin que se amenacen. Fue propuesto por el ajedrecista alemán Max Bezzel en 1848. En el juego de ajedrez la reina amenaza a aquellas fichas que se encuentren en su misma fila, columna o diagonal. Las 8 reinas consiste en colocar sobre un tablero de ajedrez ocho reinas sin que estas se den jaques entre ellas. Para resolver este problema emplearemos un esquema vuelta atrás (o Backtracking).

Page 4: Algoritmo Prim

Contenido

 [ocultar]

1   Historia

2   Planteamiento del Problema

o 2.1   Establecimiento del Algoritmo

o 2.2   Descripción del Algoritmo

3   El problema de las n Reinas

4   Soluciones al Problema de las Ocho Reinas

5   Referencias

6   Véase también

7   Enlaces externos

o 7.1   Enlaces a Soluciones

[editar]Historia

El problema fue originalmente propuesto en 1848 por el ajedrecista Max Bezzel, y durante los años, muchos matematicos, inluyendo aGauss y a Georg Cantor, han trabajado en este problema y lo han generalizado a n-reinas. Las primeras soluciones fueron provistas por Franz Nauck en 1850. Nauck también se aboco a las n-reinas (en un tablero de nxn de tamaño arbritario). En 1874, S. Günther propuso un método para hallar las soluciones usando determinantes, y J.W.L. Glaisher redefinio su aproximación.

Edsger Dijkstra uso este problema en 1972 para ilustrar el poder de la llamada programación estructurada. Él publico una altamente detallada descripción del desarrollo del algoritmo de backtracking, "depth-first".

Este acertijo apareció en el popular juego de computadora de los '90 llamado "The 7th Guest".

[editar]Planteamiento del Problema

Como cada reina puede amenazar a todas las reinas que estén en la misma fila, cada una ha de situarse en una fila diferente. Podemos representar las 8 reinas mediante un vector[1-8], teniendo en cuenta que cada índice del vector representa una fila y el valor una columna. Así cada reina estaría en la posición (i, v[i]) para i = 1-8.

Page 5: Algoritmo Prim

Ejemplo de dos reinas amenazadas en el tablero de 4 por 4.

El vector (3,1,6,2,8,6,4,7) significa que la reina 1 esta en la columna 3, fila1; la reina 2 en la columna 1, fila 2; la reina 3 en la columna 6, fila 3; la reina 4 en la columna 2, fila 4; etc... Como se puede apreciar esta solución es incorrecta ya que estarían la reina 3 y la 6 en la misma columna. Por tanto el vector correspondería a una permutación de los ocho primeros números enteros.

El problema de las filas y columnas lo tenemos cubierto, ¿pero qué ocurre con las diagonales? Para las posiciones sobre una misma diagonal descendente se cumple que tienen el mismo valor fila − columna, mientras que para las posiciones en la misma diagonal ascendente se cumple que tienen el mismo valor fila + columna. Así, si tenemos dos reinas colocadas en posiciones (i,j) y (k,l) entonces están en la misma diagonal si y solo si cumple:

i − j = k − l o i + j = k + l

j − l = i − k o j − l = k − i

Con todas las consideraciones tenidas en cuenta podemos aplicar el esquema de vuelta atrás para implementar las ocho reinas de una manera realmente eficiente. Para ello, reformulamos el problema como un problema de búsqueda en un árbol. Decimos que en un vector   de enteros entre 1 y 8 es k-prometedor, para   , si ninguna de

las k reinas colocadas en las posiciones   amenaza a ninguna de las otras. Las soluciones a nuestro problema se corresponden con aquellos vectores que son 8-prometedores.

Page 6: Algoritmo Prim

[editar]Establecimiento del AlgoritmoSea N el conjunto de vectores de k-prometedores,  ,

sea   el grafo dirigido tal que   si y solo si existe un entero k, con   tal que

U es k-prometedor

V es (k + 1)-prometedor Ui = Vi para todo 

Este grafo es un árbol. Su raíz es el vector vacío correspondiente a k = 0. sus hojas son o bien soluciones (k = 8), o posiciones sin salida (k < 8). Las soluciones del problema de las ocho reinas se pueden obtener explorando este árbol. Sin embargo no generamos explícitamente el árbol para explorarlo después. Los nodos se van generando y abandonando en el transcurso de la exploración mediante un recorrido en profundidad.

Esquema reducido del árbol de soluciones.

Hay que decidir si un vector es k-prometedor, sabiendo que es una extensión de un vector (k − 1)-prometedor, únicamente necesitamos comprobar la última reina que haya que añadir. Este se puede acelerar si asociamos a cada nodo prometedor el conjunto de columnas, el de diagonales positivas (a 45 grados) y el de diagonales negativas (a 135 grados) controlados por las reinas que ya están puestas.

[editar]Descripción del AlgoritmoA continuación se muestra el algoritmo que arroja la solución de nuestro problema, en el cual   es un vector global. Para imprimir todas las

soluciones, la llamada inicial es  .

procedimiento 

Page 7: Algoritmo Prim

//  es k-prometedor//

// //

//

//

//

//

si   entonces //un vector 8-

prometedor es una solución//

escribir 

si no //explorar las extensiones (k + 1)-

prometedoras de sol//

para   hasta   hacer

si   y   

y   entonces

//  es (k + 1)-

prometedor//

El algoritmo comprueba primero si k = 8, si esto es cierto resulta que tenemos ante nosotros un vector 8-prometedor, lo cual indica que cumple todas las restricciones originando una solución. Si k es distinto de 8, el algoritmo explora las extensiones (k + 1)-prometedoras, para ello realiza un bucle, el cual va de 1 a 8, debido al número de reinas. En este bucle se comprueba si entran en jaque las reinas colocadas en el tablero, si no entran en jaque, se realiza una recurrencia en la cual incrementamos k (buscamos (k + 1)-prometedor) y añadimos la nueva fila, columna y diagonales al conjunto de restricciones. Al realizar la recurrencia hemos añadido al vector sol una nueva reina la cual no entra en jaque con ninguna de las anteriores, además hemos incrementado el conjunto de restricciones añadiendo una nueva fila, columna y diagonales (una positiva y otra negativa) prohibidas.

[editar]El problema de las n Reinas

Page 8: Algoritmo Prim

El problema de las 8 Reinas es generalizado por el problema de las n Reinas. El problema consiste en colocar n Reinas en un tablero de ajedrez de   de tal manera que ninguna de las Reinas quede atacando a otra.

Su análisis y solución es isomorfo al de las 8 Reinas.

[editar]Soluciones al Problema de las Ocho Reinas

El problema de las ocho reinas tiene 92 soluciones, de las cuales 12 son esencialmente distintas, es decir las 92 soluciones existentes se pueden

obtener a partir de simetrías, rotaciones y traslaciones de las 12 soluciones únicas,

que se muestran a continuación:

Solución única 1 Solución única 2 Solución única 3

Solución única 4 Solución única 5 Solución única 6

Page 9: Algoritmo Prim

Solución única 7 Solución única 8 Solución única 9

Solución única 10 Solución única 11 Solución única 12

Codigo en java

tablero = new Array(new Array(),new Array(),new Array(),new Array(),new Array(),new Array(),new Array(),new Array());

restricciones = new Array();var cosa = new Array();var solucion = 0;var limite = 0;var reinas = 0;for (i=0; i<8; i++) {

for (k=0; k<8; k++) {

Page 10: Algoritmo Prim

tablero[i][k] = 0;}restricciones[i] = -1;cosa[i] = "";

}for (i=0; i<8; i++) {

for (k=0; k<8; k++) {if (restricciones[i]<="0)" tablero[y]

[x]--;="" y++;="" x="" style="padding-top: 0em; padding-right: 0em; padding-bottom: 0em; padding-left: 0em; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; ">=0; x--) {

if (tablero[y][x]<=0) {tablero[y][x]--;

}y--;

}y = i;for (x=k; x>=0; x--) {

if (tablero[y][x]<=0) {tablero[y][x]--;

}y++;

}y = i;for (x=k; x<8; x++) {

if (tablero[y][x]<=0) {tablero[y][x]--;

}y--;

}break;

} else if (k == 7) {restricciones[i] = -1;i--;

for (k=0; k<8; k++) {if (tablero[i][k]>0) {

for (x=0; x<8; x++) {if (x != k) {

tablero[i][x]++;

}if (x != i) {

tablero[x][k]++;

}}y = i;for (x=k; x<8; x++) {

Page 11: Algoritmo Prim

if (tablero[y][x]<0) {

tablero[y][x]++;

}y++;

}y = i;for (x=k; x>=0; x--) {

if (tablero[y][x]<0) {

tablero[y][x]++;

}y--;

}y = i;for (x=k; x>=0; x--) {

if (tablero[y][x]<0) {

tablero[y][x]++;

}y++;

}y = i;for (x=k; x<8; x++) {

if (tablero[y][x]<0) {

tablero[y][x]++;

}y--;

}tablero[i][k] = 0;restricciones[i] = k;

}}k = -1;

}}

}

Other codeimport java.util.*;

public class Hanoi {

Page 12: Algoritmo Prim

public static void main(String args[]){

int n;

Scanner sc=new Scanner(System.in);

System.out.print("Escriba el número de discos en la torre de hanoi: ");

n=sc.nextInt();

while(n<0){

System.out.print("Error, reescriba el número de discos en la torre:

");

n=sc.nextInt();

}

algoritmoHanoi(n,"Primera Torre","Segunda Torre","Tercera Torre");

}

public static void algoritmoHanoi(int n, String from, String temp, String to) {

if (n == 0) return;

algoritmoHanoi(n-1, from, to, temp);

System.out.println("Mover disco " + n + " de " + from + " a " + to);

algoritmoHanoi(n-1, temp, from, to);

}

}

Código Fuente torres hanoi :

import java.awt.*;

import java.applet.*;

public class Hanoi extends Applet

{

static final int XDOTS = 400;

static final int YDOTS = 200;

static final int NULL = -1;

static final int MAX = 20;

static final int MIN = 3;

static final int MAXCOLS = 6;

static final int MINCOLS = 3;

static final Color cfondo=new Color(228,233,243);

static final Color cbarra=Color.black;

Page 13: Algoritmo Prim

static final Color cfin =Color.red;

static final Color ctorre=Color.blue;

boolean first=true;

int origen,destino;

int movimientos;

int h[] = new int[MAXCOLS];

int Ficha[][] = new int[MAXCOLS][MAX];

int Centorr[] = new int[MAXCOLS];

Button B[] = new Button[MAXCOLS];

TextField TFTorres, TFCols, TFMovimientos;

int numtorres=5, numcols=3;

void Parametros()

{

String param;

param = getParameter("TORRES");

if (param != null) numtorres = Integer.parseInt(param);

param = getParameter("COLS");

if (param != null) numcols = Integer.parseInt(param);

}

public void init()

{

int i;

setBackground(cfondo);

resize(XDOTS,YDOTS);

if (first)

{

Parametros();

Herramientas();

first=false;

Page 14: Algoritmo Prim

}

for (i=0; i< MAXCOLS; i++)

if (i< numcols) B[i].enable();

else B[i].disable();

for (i=0; i< numcols; i++)

Centorr[i]=(XDOTS/(numcols+1))*(i+1);

h[0]=numtorres;

for (i=1; i< numcols; i++)

h[i]=0;

for (i=0; i< numtorres; i++)

Ficha[0][i]=numtorres-i;

movimientos=0;

origen=destino=NULL;

}

public void Herramientas()

{

setLayout(new BorderLayout());

Panel p= new Panel();

p.setBackground(cfondo);

for (int i=0; i< MAXCOLS; i++)

p.add(B[i]=new Button(Integer.toString(i+1));

p.add(new Button("Cancelar"));

p.add(new Button("Resolver"));

p.add(new Button("Nueva"));

add("South",p);

Panel g= new Panel();

g.setBackground(cfondo);

g.add(new Label("Columnas"));

g.add(TFCols= new TextField(Integer.toString(numcols));

Page 15: Algoritmo Prim

g.add(new Label("Torres"));

g.add(TFTorres=new TextField(Integer.toString(numtorres));

g.add(new Label("Movimientos"));

TFMovimientos=new TextField("0",8);

TFMovimientos.disable();

g.add(TFMovimientos);

add("North",g);

}

public void Dibujar_Torres (Graphics g, Color coltorr)

{

int x,y, Long;

int l,k;

int anchomin=(Centorr[1]-Centorr[0])/numtorres;

int altotorre=(YDOTS-85)/numtorres;

g.setColor(cbarra);

for (k=0; k< numcols; k++)

g.fillRect(Centorr[k]-1, 35, 2, YDOTS-75);

g.setColor(coltorr);

for (k=0; k< numcols; k++)

for (l=0; l< h[k]; l++)

{

Long=anchomin*Ficha[k][l];

x=(Centorr[k]-(Long/2));

y=YDOTS-60-l*altotorre;

g.fillRect(x,y,Long,altotorre-altotorre/3);

}

}

public void paint(Graphics g)

{

Page 16: Algoritmo Prim

Dibujar_Torres(g, ctorre);

TFMovimientos.setText(Integer.toString(movimientos));

for (int i=1; i< numcols; i++)

if (h[i]==numtorres) Final();

}

public void Final()

{

Dibujar_Torres(getGraphics(), cfin);

}

boolean valido(int origen, int destino)

{

if (origen==NULL || destino==NULL || origen==destino) return false;

if (h[origen]==0) return false;

if (h[destino]==0) return true;

if (Ficha[destino][h[destino]-1]< Ficha[origen][h[origen]-1]) return false;

return true;

}

public void Resolver()

{

Mover(numtorres,0,1,numcols-1);

}

void Desplazar(int origen, int destino)

{

h[origen]--;

Ficha[destino][h[destino]]=Ficha[origen][h[origen]];

h[destino]++;

movimientos++;

}

void Mover(int Numero, int Comienzo, int Auxiliar, int Final)

Page 17: Algoritmo Prim

{

int varaux;

for (int i=Numero; i>0; i--)

{

Mover(i-1,Comienzo,Final,Auxiliar);

Desplazar(Comienzo,Final);

update(getGraphics());

varaux=Comienzo;

Comienzo=Auxiliar;

Auxiliar=varaux;

}

}

public boolean action(Event e, Object o)

{

if (e.target instanceof Button)

{

int i;

for (i=0 ; i< numcols; i++)

if ((Integer.toString(i+1)).equals(e.arg))

{

if (origen==NULL)

{

origen=i;

B[origen].disable();

}

else

{

destino=i;

for (i=0; i< numcols; i++)

Page 18: Algoritmo Prim

B[i].enable();

}

break;

}

if( "Nueva".equals(e.arg) || "Resolver".equals(e.arg))

{

numtorres=Integer.parseInt(TFTorres.getText());

numcols =Integer.parseInt(TFCols.getText());

if (numtorres< MIN) numtorres=MIN;

else if (numtorres>MAX) numtorres=MAX;

if (numcols< MINCOLS) numcols=MINCOLS;

else if (numcols>MAXCOLS) numcols=MAXCOLS;

TFTorres.setText(Integer.toString(numtorres));

TFCols.setText(Integer.toString(numcols));

TFMovimientos.setText("0");

init();

}

if( "Cancelar".equals(e.arg))

{

origen=destino=NULL;

for (i=0; i< numcols; i++)

B[i].enable();

}

if( "Resolver".equals(e.arg)) Resolver();

if (valido(origen,destino))

{

Desplazar(origen,destino);

origen=destino=NULL;

}

Page 19: Algoritmo Prim

repaint();

return true;

}

return false;

}

public String getAppletInfo()

{

return "Nombre : Torres de Hanoi\r\n" +

"Autor : Manuel Barrera \r\n" +

"e-mail : [email protected].\r\n";

}

}