Está en la página 1de 41

Técnicas para el Diseño de

Algoritmos

Algoritmos

„ Algoritmos voraces
„ Divide y conquista
„ Programación dinámica
„ Backtracking

1
Algoritmos Voraces

Algoritmos Voraces

„ Algoritmos que implementan una búsqueda miope


‰ Toman decisiones de acuerdo a la información que tienen
en el momento
„ Ventajas:
‰ Fáciles de implementar
‰ Eficientes cuando funcionan de acuerdo al problema
„ Desventajas:
‰ Para problemas con un gran tamaño en el espacio de
búsqueda, suelen ser ineficientes

2
Algoritmos Voraces

„ Suelen utilizarse en problemas de


optimización
„ Ejemplo
‰ Considere que nos encontramos en un país con
monedas de 100, 20, 10, 5 y 1
‰ Se debe de crear un algoritmo que permita dar el
menor número de monedas
‰ Si se desea dar a una persona 289 pesos, ¿Qué
monedas utilizarías?

Algoritmos Voraces

„ El algoritmo es “voraz” porque selecciona la


mayor denominación disponible en el
momento y que aun pueda generar una
solución válida
„ ¿Qué problemas crees que se le pueden
presentar al algoritmo si alguna de las
denominaciones es limitada en cantidad?
„ ¿Siempre obtendrá la mejor solución? ¿Bajo
que condiciones el algoritmo voraz no
funcionará?

3
Ejemplo Camino Mínimo

„ Considere que se va a elaborar un programa


que dado un conjunto de ciudades unidas
entre si a través de cierto conjunto de
carreteras, determine una ruta que permita
visitar a todas las ciudades

Mapa

4
Ejemplo Camino Mínimo

„ El problema de visitar a todas las ciudades


se relaciona con el problema de construir un
“arbol de recubrimiento mínimo”
„ ¿Cómo atacarlo a través de la técnica de
algoritmos voraces?

Árbol de Recubrimiento Mínimo

„ Posibles soluciones
‰ Comenzar con un conjunto vacío T y seleccionar
en cada etapa la arista más barata no
considerada previamente
‰ Seleccionar un nodo y construir un árbol a partir
de él

„ ¿Qué técnica, desde tu perspectiva es la


mejor? ¿Cuál si funcionará?

5
Algoritmo de Kruskal

„ El algoritmo parte de un subconjunto vacío T de


aristas
„ Se van construyendo componentes conexas, a las
cuales se les añade un arco que represente la
mínima expansión al componente conexo
„ Si una arista une a dos componentes conexas
distintas, se añade a T, en caso contrario, se
rechaza
„ Al finalizar el algoritmo, sólo queda un componente
conexo

Algoritmo de Kruskal

6
Algoritmo de Kruskal

Algoritmo de Kruskal

„ ¿Qué problemas identificas en este


algoritmo?
„ ¿En qué tipo de problemas aplicarías el
algoritmo de Kruskal?

7
Algoritmo de PRIM

„ En el algoritmo de Kruskal, los árboles


crecen de forma arbitraria Æ NO se tiene un
estado inicial predeterminado
„ Una alternativa a este algoritmo es PRIM, en
cual parte de una raíz seleccionada
arbitrariamente
‰ En cada expansión, se añade una nueva rama al
árbol ya construido

Algoritmo de PRIM

„ function PRIM (G= (V,A))


„ TÅ∅
„ B Å {v ∈ V} (seleccionado arbitrariamente)
„ Mientras B ≠ V hacer
‰ Buscar e = {u,v}, e ∈ A: u ∈ B, v ∈ V \ B
‰ T Å T ∪ {e}
‰ B Å B ∪ {v}
„ Regresar T

8
Algoritmo de PRIM

„ Para el ejemplo anterior y partiendo del


vértice “1”, ¿Cuál sería el resultado?
„ ¿Cómo se implementaría en una
computadora?

El problema de Caminos Mínimos

„ Otro problema clásico en grafos consiste en


determinar, dado un origen, el camino
mínimo que va desde un origen predefinido
hasta cualquier nodo dentro del grafo
‰ Entrada: G = (V, A)
‰ V = {v1, …, vn}, A ⊆ {(vi, vj): vi, vj ∈ V, vi ≠ vj}
‰ ∀ e = (vi, vj) ∈ A: w(e) representa un peso positivo
asociado al arco (vi, vj)
‰ Salida: D (matriz de distancias) y P (matriz de
caminos)

9
Algoritmo de Dijkstra

„ El problema se puede resolver a través de un


algoritmo conocido como Dijkstra
„ El algoritmo utiliza las siguientes variables:
‰ v1: nodo origen
‰ S: conjunto de vértices ya seleccionados
‰ C = V \ S (conjunto de vértices no seleccionados)
‰ D: matriz que almacena el costo entre el nodo
origen y cada uno de los vértices en G
‰ L: matriz de pesos entre todas las aristas dirigidas

Algoritmo de Dijkstra

function Dijkstra(L[][])
C Å {1, 2, 3, …, n}
D[1] Å 0, P[1] Å {1}
Para i = 2 hasta n hacer
D[i] Å ∞, P[i] Å {}
Mientras |C| > 1 hacer
v Å min{D[u]: u ∈ C}
C Å C \ {v}
para cada w ∈ C hacer
si D[w]>D[v]+L[v,w] entonces D[w]ÅD[v]+L[v,w]
P[w]ÅP[v]∪{w}

10
Ejemplo 1

10 50

5 2
100 30

20
5
10

4 3
50

Ejemplo 2

11
Divide y Vencerás

Divide y Vencerás

„ Técnica que consiste en dividir un problema


en subproblemas más pequeños, para
combinar los resultados parciales para
obtener el resultado final
‰ Más sencillo resolver casos más pequeños
‰ Para mayor eficiencia, se busca que los
subproblemas generados tengan una dimensión
similar
‰ Se debe verificar que la solución del problema
original puede obtenerse a través de soluciones
parciales

12
Multiplicación de Números Grandes

„ El algoritmo clásico de multiplicación realiza


n2 multplicaciones y “n” sumas para 2
números con “n” cifras

981
1234
3924
2943
1962
981
1210554

Estrategia

„ Disminuir el número de multiplicaciones


dividiendo los números a multiplicar
‰ A) Por simplicidad se considera que los
multiplicandos tienen la misma dimensión
„ En el ejemplo, 981 Æ 0981, 1234 Æ 1234
‰ B) Se parten por mitades a ambos operandos
„ 0981: w = 09, x = 81 = 102w + x
„ 1234: y = 12, z = 34 = 102y + z

13
Estrategia

‰ C) Se realiza la multiplicación con respecto a la


descomposición de los números
„ 981 * 1234 = (102w + x) (102y + z)
= 104 wy + 102 (wz + xy) + xz
= 1080000 + 127800 + 2754 = 1210554
‰ En esta operación, las operaciones “wz” y “xy” se
puede reescribir como:
„ r = (w + x) (y + z) = wy + (wz + xy) + xz

Estrategia

„ De lo anterior se procede de la siguiente


manera:
‰ p = wy = 09 * 12 = 108
‰ q = xz = 81 * 34 = 2754
‰ r = (w + x) (y + z) = 90 * 46 = 4140
„ Por tanto.
‰ 981 * 1234 = 104p + 102(r – p – q) + q
= 1080000+127800+2754 = 1210554

14
Observaciones

„ Para este ejemplo, se sustituyó una multiplicación


por 4 sumas
„ ¿Cuál es el ahorro real que se logra con esta forma
alternativa de multiplicar números?
‰ Forma tradicional: h(n) = cn2
‰ Técnica divide y vencerás
„ Si g(n) representa el costo de realizar las operaciones sin
tomar en cuenta las tres multiplicaciones y considerando que
las multiplicaciones se realizan de forma tradicional, tenemos
que:
3 h(n/2)+g(n) = 3c(n/2)2+g(n) = ¾ cn2+g(n) = 3/4h(n)+g(n)

Observaciones

„ Es evidente que ambos son algoritmos


cuadráticos, ya que estamos considerando
que el orden de las multiplicaciones de los
números mitad se realizan de forma
tradicional (orden cuadrático)
„ Sin embargo, si los números mitad son
suficientemente grandes, se puede aplicar de
forma recursiva la técnica ya analizada

15
Observaciones

„ Por tanto, para saber la complejidad del


algoritmo original, se llega a una recurrencia
de la forma
t(n) = 3t(n/2) + g(n)
„ Notemos que g(n) es una expresión que
representa corrimientos y sumas entre
números con “n” digitos, por lo que O(g(n)) =
n
Æ t(n) = 3t(n/2) + n

Complejidad Multiplicación de Números


Divide y Vencerás
„ De lo anterior se concluye que
Θ(t(n)) = nlog 3 para n potencias de 2

„ log2 3 ≈ 1.585 < 2, por lo que la mejora con


respecto al algoritmo tradicional de
multiplicación para números grandes es
significativo

16
Comentario

„ La pregunta clave en cualquier algoritmo de


divide y vencerás es
¿Cuándo dejar de dividir los casos?
„ Esta pregunta se debe de responder, ya que
para casos pequeños, la técnica de divide y
vencerás será sensiblemente más lenta que
el algoritmo tradicional

Cuestión de Análisis

„ ¿Cómo multiplicar números impares?


„ ¿Qué sucede si la longitud de los números a
multiplicar es diferente?
‰ Se puede demostrar que si u y v son los números
a multiplicar con dimensión m y n
respectivamente, el algoritmo divide y vencerás
será más lento que el algoritmo clásico si m < n1/2

17
Búsqueda Binaria

„ Problema en el que, dado un arreglo ordenado de


forma ascendente T con “n” elementos, verificar si
existe un número “x” en el arreglo, regresando la
posición en el arreglo si es que existe
„ Algoritmo tradicional: búsqueda secuencial
Costo: (n)
function secuential(int T[], int x)
{ para i Å 1 hasta n hacer
si T[i] ≥ n entonces devolver i
devolver i+1;
}

Búsqueda Binaria

„ Estrategia: “dividir” al arreglo T por la mitad y


verificar si x se encuentra en la parte superior
o inferior del arreglo.
‰ El algoritmo se ejecuta de forma recursiva
buscando x ahora en cualquiera de las mitades
del arreglo hasta encontrarlo o bien, hasta que el
arreglo en el cual se busca sea vacío

18
Búsqueda Binaria
function busquedabin(T[], x)
{ si n = 0 o x > T[n] entonces devolver n+1;
devolver binrec(T, 1, n, x);
}

function binrec(T[], int i, int j, x)}


{ si i = j entonces
si T[i] = x regresar i
en caso contrario, regresar -1
k Å int((i + j) / 2)
si x ≤ T[k] entonces regresar binrec(T, i, k, x)
regresar binrec(T, k+1, j, x)
}

Análisis

„ Notemos que en cada llamado recursivo, el


algoritmo procesará la mitad del arreglo que
se procesa en la iteración, por lo que:
T(n) = T(n/2) + g(n)
„ Notemos que g(n) representa el costo de
realizar la operación y división. Por
simplicidad, consideramos que tiene un costo
constante (para números muy grandes NO
es constante)
„ Por tanto, concluimos que T(n) ∈ Θ(log2 n)

19
Problema de Ordenar un Arreglo

„ Otro problema clásico dentro de la estrategia


divide y vencerás es ordenar un arreglo
„ Existen varias técnicas que implementan la
técnica divide y vencerás
‰ Por Fusión (mergesort)
‰ Ordenación rápida (quicksort)

Ordenación por Fusión

„ Al igual que todas las técnicas de divide y


vencerás, se divide el arreglo en dos partes y
se procesa cada parte de forma recursiva,
hasta que su dimensión es pequeña para
utilizar un algoritmo básico de ordenación
„ Al finalizar, se requiere de un algoritmo
eficiente que fusione los arreglos ordenados

20
Ordenación por Fusión

procedimiento fusionar(U[m+1], V[n+1], T[m+n])


{ i, j Å 1
U[m+1] Å ∞
V[n+1] Å ∞
para k Å 1 hasta m+n hacer
si U[i] < V[j]
entonces T[k] Å U[i], i Å i + 1
si no T[k] Å V[j], j Å j + 1
}

Ordenación por Fusión

procedimiento ordenarporfusion(T[n])
{ si n es suficientemente pequeño
entonces ordenarporinsertar(T)
en caso contrario
U[1, …, n/2] Å T[1, …, n/2]
V[1, …, n/2] Å T[n/2 + 1, …, n]
ordenarporfusion(U)
ordenarporfusion(V)
fusionar(U,V,T)
}

21
Análisis

„ Notemos que:
‰ Separar la matriz T en dos partes requiere un tiempo lineal
‰ La función fusionar también requiere un tiempo lineal
‰ Sea g(n) ∈ Θ(n)
„ Por tanto, la complejidad de la función queda
definida como:
T(n) = 2T(n/2)) + g(n)
„ De lo anterior se concluye que
T(n) ∈ Θ(n log2 n)

Ordenación Rápida

„ Este algoritmo parte de la premisa que se


desea ordenar un arreglo en el cual los
números se encuentran aleatoriamente
desordenados
„ Divide al arreglo en dos partes, ubicando un
“pivote” que definirá como se parte al arreglo
(no necesariamente es la mitad del arreglo)

22
Ordenación Rápida

Ordenación Rápida

„ Si el arreglo inicial se encontraba


aleatoriamente desordenado, entonces el
punto de partición tenderá a estar cerca de la
mitad del arreglo. En caso contrario el
algoritmo se vuelve ineficiente

23
Análisis

„ “partition” recorre de forma completa al arreglo que


se procesa, por tanto, tiene un costo lineal con
respecto a la dimensión del arreglo procesado
„ “partition” regresa un valor “q” que siempre se
encuentra entre 1 y n, donde cada valor tiene la
misma probabilidad de aparecer (1/n)
„ Por tanto, el costo de ejecutar quicksort es:

1 n
t ( n) = ∑ ( g (n) + t (q − 1) + t (n − 1))
n i =1

Análisis

„ Es evidente que esta expresión no se puede


resolver de forma directa con las técnicas de
solución de recurrencias vistas hasta el
momento
„ Sin embargo, considerando una distribución
aleatoria de los números, el valor de “q”
tenderá a ser un valor central, acercandose a
n/2, lo que deja ver que para un caso
promedio, quicksort tenderá a comportarse
como Θ(n log2 n)

24
Multiplicación de Matrices

„ Sean A, B dos matrices de nxn y sea C la matriz producto


„ Para calcular cada elemento C[i,j], el algoritmo clásico utiliza
la expresión:
n
C[i, j ] = ∑ A[i, k ] * B[k , j ]
k =1

„ COSTO: Considerando que las sumas y productos son


operaciones elementales, entonces calcular cada entrada
tiene un costo Θ(n)
„ Dado que hay que calcular n2 entradas, el costo total de la
multiplicación es de Θ(n3)

Algoritmo de Strassen

„ Considere dos matrices A y B

 a1,1 a1, 2   b1,1 b1, 2 


A=  , B= 
a2,1 a2, 2  b2,1 b2, 2 
„ Sean las operaciones siguientes:
‰ m1 = (a2,1+ a2,2 – a1,1) (b2,2 – b1,2 + b1,1)
‰ m2 = a11 b1,1
‰ m3 = a1,2 b2,1
‰ m4 = (a1,1 – a2,1) (b2,2 – b1,2)
‰ m5 = (a2,1 + a22) (b1,2 – b1,1)
‰ m6 = (a1,2 – a2,1 + a,1,1 – a2,2) (b2,2)
‰ m7 = a2,2 (b1,1 + b2,2 – b1,2 – b2,1)

25
Algoritmo de Strassen

„ A partir de estas operaciones, la multiplicación de


las matrices se define como:

 m2 + m3 m1 + m2 + m5 + m6 
C=
m1 + m2 + m4 − m7 m1 + m2 + m5 + m5 

Algoritmo de Strassen

„ En este ejemplo, la multiplicación se efectúa


a través de:
‰ 14 sumas y 7 multiplicaciones
„ El algoritmo tradicional utiliza 4 sumas y 8
multiplicaciones
„ En primera instancia el algoritmo no
representa ningún beneficio sustancial

26
Algoritmo de Strassen

„ Sin embargo, si se sustituye cada entrada de


las matrices por una matriz de n x n,
entonces es capaz de multiplicar 2 matrices
de 2n x 2n con
‰ Siete multiplicaciones de matrices n x n
‰ Cierto número de sumas y restas de matrices n x
n
„ De lo anterior, se puede inferir que esta
técnica tendrá el siguiente costo:
T(n) = 7T(n/2) + g(n), donde g(n) ∈ Θ(n2)

Algoritmo de Strassen

„ Resolviendo la recurrencia, se determina


que:

T(n) ∈ Θ (nlog 7) ≈ Θ (n2.81) < Θ (n3)

27
Programación Dinámica

Programación Dinámica

„ La programación dinámica surge como


respuesta para evitar la duplicidad de
cálculos operaciones
‰ Cuando se resuelve un problema a través de
subproblemas, es probable que dichos
subproblemas tengan operaciones comunes entre
sí (no son independientes)
‰ La programación dinámica consiste en identificar
y guardar los resultados de los cálculos comunes
para su uso posterior

28
Ejemplo 1: Coeficiente Binomial

„ El coeficiente binomial se define de la siguiente


forma:
1 si k = 0, k = n
n 
  =  n − 1  n − 1
 k    +   si 0 < k < n
 k − 1  k 

„ La solución trivial a este problema es:


funcion C(n,k)
{ si k = 0 ó k = n entonces regresar 1
regresar C(n-1, k-1) + C(n-1,k)
}

Ejemplo 1: Coeficiente Binomial

„ Es evidente que muchos valores C(i,j) se calculan


varias veces
„ Por ejemplo, sea C(5,3) genera:
 5  4  4
C   = C   + C  
 3  2  3

 4  3  3  4  3  3
C   = C   + C   C   = C   + C  
 2 1  2  3  2  3

 3  2  2  3  2  2
C   = C   + C   C   = C   + C  
1 0 1  2 1  2

 2 1 1
C   = C   + C  
1 0 1

29
Ejemplo 1: Coeficiente Binomial

Ejemplo 2: Devolver Cambio

„ Dado un conjunto de “n” denominaciones d1,


…, dn, se debe de dar una cantidad C con
dichas denominaciones, minimizando el
número de monedas a dar
„ Para analizar el problema desde la
perspectiva de programación dinámica,
asumamos:
‰ De inicio que se tiene un suministro ilimitado de
cada denominación

30
Ejemplo 2: Devolver Cambio

„ Para resolver el problema con programación


dinámica, se considera una matriz C donde:
‰ CnxN: una fila por cada denominación y una
columna para las cantidades que van desde 0
hasta N
‰ C[i,j] representa el # mínimo de monedas para dar
la cantidad “j”, utilizando monedas sólo de
denominación menor o igual a “i”
‰ La solución general estará dada por C[n,N]

Ejemplo 2: Devolver Cambio

„ Asignación de valores de la matriz C:


‰ La matriz se llena fila a fila (arribaÆabajo) o
columna a columna, (izquierdaÆderecha)
‰ La 1a columna se rellena con 0’s (no se puede dar
$0 con monedas de valor mayor o igual a uno)
‰ Para dar $j pesos con monedas de denominación
menor o igual a “i”, C[i,j] se tienen dos opciones:
„ No utilizar monedas de denominación “di” (C[i,j]=C[i-1,j])
„ Utilizar una moneda de denominación “di” más el
número de monedas para dar el resto (C[i,j-di])
C[i,j] = min {C[i-1,j], 1 + C[i,j-di]}

31
Ejemplo 2: Devolver Cambio

Cantidad 0 1 2 3 4 5 6 7 8
d1 = 1 0 1 2 3 4 5 6 7 8
Monedas

d2 = 4 0 1 2 3 1 2 3 4 2
d3 = 6 0 1 2 3 1 2 1 2 2
NOTAS:
• Si alguno de los elementos a comparar caen fuera de la matriz, se consideran
a estos valores como +∞
• Si ambos elementos a comparar caen fuera de la tabla, se asigna +∞ a la
casilla correspondiente

Ejemplo 2: Devolver Cambio

„ ¿Como determinamos que monedas se


necesitan dar a partir de la matriz C?
„ ¿Qué pasa si el número de monedas que se
suministran es limitado? ¿Cómo se podría
mejorar el algoritmo para considerar este
hecho?
„ ¿Qué tiempo requiere el algoritmo para
ejecutarse?

32
Ejemplo 3: Algoritmo de Floyd

„ Considere un grafo dirigido G = (V, A), donde


se desea calcular la distancia mínima entre
cada par de nodos
‰ V = {v1, …, vn}
‰ A ⊆ {(vi, vj): vi, vj ∈ V}
‰ L matriz de distancias, donde L[i,j] es la distancia
entre el vértices vi y vj que son unidos por un arco
‰ L[i,i] = 0, 1 ≤ i ≤ n
‰ L[i,j] = ∞ si (vi, vj) ∉ A

Ejemplo 3: Algoritmo de Floyd

„ El algoritmo de Floyd consta de los


siguientes pasos:
‰ Se construye una matriz D de dimensión nxn (por
notación, Dk representa los valores de la matriz D
en la k-ésima iteración)
‰ Se inicializa D0 Å L
‰ Se realizan n iteración, donde para la k-ésima
iteración Dk da la longitud más corta entre
cualquier par de nodos, utilizando sólo los
vértices v1, …, vk

33
Ejemplo 3: Algoritmo de Floyd

„ En cada iteración k, para todo par de nodos


(vi, vj) se verifica si existe un camino entre vi
y vj pasando por vk y que sea menor al
camino óptimo actual
Dk[i,j] = min{Dk-1[i,j], Dk-1[i,k] + Dk-1[k,j]}
„ En este algoritmo se utiliza el principio de
OPTIMALIDAD

Ejemplo 3: Algoritmo de Floyd


function Floyd(L[], int n)
{ D Å L;
para i Å 1 hasta n hacer
para j Å 1 hasta n hacer
P[i][j] Å {} //matriz para recuperar los caminos
para k Å 1 hasta n hacer
para i Å 1 hasta n hacer
para j Å 1 hasta n hacer
si D[i][k] + D[k][j] < D[i][j]
D[i][j] Å D[i][k] + D[k][j]
P[i][j] Å P[i][j] ∪ {k}
regresar D, P;
}

34
Ejemplo 3: Algoritmo de Floyd
 0 5 ∞ ∞
50 0 15 5 
D0 = L =  
30 ∞ 0 15
 
15 ∞ 5 0 
30
1 3
15  0 5 ∞ ∞  0 5 20 20
50 0 15 5  50 0 15 5 
5 50 5 D1 =   D2 =  
15 30 35 0 15 30 35 0 15 
   
15 20 5 0  15 20 5 0 
15

2 4
5
 0 5 20 10  0 5 15 10
45 0 15 5  20 0 10 5 
D3 =   D4 =  
30 35 0 15 30 35 0 15
   
15 20 5 0  15 20 5 0 

Vuelta Atrás
(Backtracking)

35
Introducción

„ Técnica ampliamente utilizada para resolver


problemas a través de una búsqueda exhaustiva
‰ Proporciona un método sistemático de generar todas las
posibles soluciones
‰ A partir de una solución parcial de tamaño “k”, se genera
una nueva solución de tamaño “k+1” (a partir de una
expansión)
„ Si la solución “k+1” es válida el proceso de expansión
continúa
„ En caso contrario, se abandona dicha solución y se regresa a
la solución de dimensión “k” para expandir otra posible
solución

Introducción

„ En el proceso de expansión:
‰ No se tienen reglas fijas para ejecutarla –
dependiente del problema
‰ El número de combinaciones a explorar puede
crecer de forma exponencial
„ En la práctica, es necesario implementar reglas que
limiten el número de posibles expansiones
„ Hay que tener cuidado en el tipo de restricciones a
implementar (costo para ejecutarla, preservar cualquier
solución válida del problema)

36
Condiciones para Implementar
Backtracking
„ La solución parcial Sk de un problema P se debe
poder expresar como una tupla
Sk = <s1, s2, …, sk>
‰ Cada si en Sk representa un estado válido en P, donde S
es una solución parcial de P con dimensión “k”
‰ A partir de sk se busca un conjunto E = {st: st es un estado
válido de P y st no forma parte de Sk}
‰ Una expansión consiste en seleccionar un sx ∈ E:
„ Sk+1 = < s1, s2, …, sk, sx>
„ E = E \ {sx}

Ejemplo: El problema de las 8 Reinas

„ Se dispone de un tablero de ajedrez (8x8). El


problema consiste en colocar en el tablero 8 reinas
de ajedrez, de tal forma que no se amenacen entre

37
Ejemplo: El problema de las 8 Reinas

„ Las soluciones se pueden representar a través del


vector S = <r1, r2, r3, …, r8>
‰ ri representa la columna donde la reina de la
i-ésima fila será colocada en el tablero

S = <4,7,3,8,2,5,1,6>

Ejemplo: El problema de las 8 Reinas

„ Restricciones:
‰ Los valores de ri están restringidos al conjunto T =
{1, 2, 3, 4, 5, 6, 7, 8}
‰ Dos reinas no pueden situarse en la misma
columna y en la misma fila
„ Por la definición de S, no hay 2 reinas en la misma fila
„ No pueden haber dos xi en S con el mismo valor
‰ Dos reinas no pueden situarse en la misma
diagonal
„ Si (x,y) y (x’,y’) representan la posición de dos reinas,
entonces |x – x’| ≠ |y – y’|

38
Ejemplo: El problema de las 8 Reinas

El problema de las Parejas Estables

„ Considere que se tienen “n” hombres y


mujeres, donde expresan su preferencia
hacia una persona del sexo opuesto a través
de dos matrices M y H
‰ Matriz M: preferencia de las mujeres hacia los
hombres
‰ Matriz H: preferencia de los hombres hacia las
mujeres

39
El Problema de las Parejas Estables

„ Las columnas de las matrices representan el orden


de preferencia (de mayor a menor) de una persona
por otra del sexo opuesto
MUJERES
Rosa Maria Petra Rita
Pepe Jose Pepe Pedro M[i,j]: preferencia de la i-ésima
Pedro Juan Jose Jose
Juan Pedro Juan Pepe
Mujer por los hombres
Jose Pepe Pedro Juan

HOMBRES
Pepe Juan Pedro José
Rosa Rita Rita Maria
Maria Petra Petra Rosa H[i,j]: preferencia del i-ésimo
Petra Rosa Rosa Petra hombre por las mujeres
Rita Maria Maria Rita

El Problema de las Parejas Estables

„ Diseñar un algoritmo que encuentre, si es que


existe, una asociación entre mujeres y hombres, de
tal forma que las parejas sean estables
„ Una pareja (h, m) es estable si no se presenta lo
siguiente:
‰ Existe una mujer m’ (con pareja (h’, m’)) tal que el hombre
h la prefiere sobre la mujer m y además, la mujer m’
prefiere a h sobre h’
‰ Existe un hombre h’’ (con pareja (h’’, m’’)) tal que la mujer
m lo prefiere sobre el hombre h y además, el hombre h’’
prefiere a m sobre m’’

40
El Problema de las Parejas Estables

„ Para resolver el problema, se considera lo


siguiente:
‰ La solución se representa con un vector A[1…n],
donde A[i] es el hombre asociado a la i-ésima
mujer (o viceversa)
„ Se utiliza un vector auxiliar (Libre) que representa que
persona aun no ha sido asociada
„ Se utilizan dos matrices, H y M, para expresar la
preferencia
„ Antes de añadir un elemento al vector, se verifica que la
persona este libre y que la asociación resulte en una
pareja estable

41

También podría gustarte