Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Mochila FRACCIONABLE
Mantenimiento de la conectividad
Mensajería urgente
Robot en circuito
Asistencia a incidencias
Almacenamiento de programas en cinta
Mezcla de cintas
Distancias entre ciudades
Recubrimiento vértices
Diseño red carreteras
Buscar en el centro y si no es seguir buscando en
la mitad correcta
Búsqueda binaria
Mergesort
Multiplicación de matrices
Programación Dinámica
ϴ(n)
SI
* Matriz de adyacencia: ϴ(n )
2
O(n log n) SI
PRIM SI
O(G) (G=gasolineras) SI
DIJKSTRA SI
O(n log n) SI
O(n log n) NO
O(n2) NO
O(n3) (DIJSKTRA) NO
O(n2) NO
O(n2) (KRUSK/PRIM) NO
ϴ(log n)
Progresión geométrica.
a→1
b→2
k→0
SI
ϴ(n log n)
Progresión geométrica.
a→2
b→2
k→1
SI
O(n )
2
SI
O(n )
2
SI
Mejorado: O(nlogn) SI
ϴ(n log n) SI
O(n2)
SI
SI
ϴ(log n) NO
ϴ(n log n) (n=fil x col) NO
O(n) NO
O(2n) NO
ϴ(log n) NO
O(nk)
ϴ(NC)
O(n3)
O(nV)
O(n3)
O(n3)
O(nm)
O(n!) SI
O(mn) SI
O(n!) SI
O(2n) SI
O(2n) SI
O(4n^2) SI
O(n2n) SI
Acotado por 28n NO
626 NO
8n^2 NO
NO
NO
O(n!) NO
O(2n) SI
O(n!) SI
O(n!) SI
O(2n) SI
O(3m) SI
Tipo Algoritmo principal
fun DyV(problema)
si trivial(problema) entonces
dev solución-trivial
sino hacer
{prob1, prob2, ...probk} ← descomponer(problema)
Divide Y Vencerás para i ∈ (1..k) hacer
soli ← DyV(probi)
fpara
fsi
dev combinar(sol1, sol2, ..., solk)
ffun
Programación Dinámica
fun VueltaAtras(v: Secuencia; k:entero)
{v es una secuencia k-prometedora}
IniciarExploracionNivel(k)
mientras OpcionesPendientes(k) hacer
extender v con siguiente opción
si SolucionCompleta(v) entonces
ProcesarSolucion(v)
sino
si Completable(v) entonces
VueltaAtras(v, k+1)
fsi
fsi
Vuelta Atrás fmientras
ffun
ϴ(n)
ϴ(log n)
Progresión geométrica.
a→1
b→2
k→0
PROCESO ϴ(nk)
• Establecimiento de las ecuaciones que representan el problema.
• Identificación de los resultados parciales.
• Construcción de la tabla de resultados parciales:
• Inicialización de la tabla con los casos base que establece la ecuación del problema.
• Establecimiento del orden de llenado de la tabla, de forma que se calculen en primer lugar los
resultados parciales que requieren pasos posteriores.
• Sustitución de las llamadas recursivas del algoritmo por consultas a la tabla.
• Aplicación: Problemas en los que sólo se puede recurrir a una búsqueda exhaustiva, recorriendo el
espacio de todas las posibles soluciones, hasta encontrar una o hasta que se haya explorado todas
las opciones.
• Debido al coste: Aplicar el conocimiento disonible sobre el problema para abandonar un camino no
válido lo antes posible.
• Intentar, antes, plantear la posibilidad de un algoritmo voraz.
• El recorrido del grafo representa el espacio de búsqueda.
• Si el grafo es infinito o muy grande, se trabaja con un grafo implícito.
• Recorrido en profundidad, avandonando las ramas no válidas.
• Se va generando una solución parcial (secuencia k-prometedora. Si se encuentra un "nodo de
fallo", se retrocede hasta encontrar una rama no explorada.
Los elementos principales del esquema de vuelta atrás son:
• lniciarExploraciónNivel( ): recoge todas las opciones posibles en que se puede extender la solución ϴ(n!)
k-prometedora.
• OpcionesPendientes( ): comprueba que quedan opciones por explorar en el nivel.
• SoluciónCompleta( ): comprueba que se haya completado una solución al problema.
• ProcesarSolución(): representa las operaciones que se quieran realizar con la solución como
imprimirla o devolverla al punto de llamada.
• Completable(): comprueba que la solución k-prometedora se puede extender con la opción elegida
cumpliendo las restricciones del problema hasta llegar a completar una solución.
Estimaciones y cota
Prim detallado
Mochila FRACCIONABLE
Mensajería urgente
* Hay un robot que se tiene que desplazar desde un
punto R a un punto S, y en el camino se puede
encontrar con obstáculos infranqueables O
* El paso por una casilla franqueable supone un gasto
de energía igual al valor que indica la casilla
* Objetivo: Llegar al punto S gastando el mínimo de
energía
* Estrategia: camino de coste mínimo (Dijkstra), si se
logra representar el circuito como un grafo.
Robot en circuito
El array F[] almacena las fechas tope de realización de los n trabajos ordenados en
orden decreciente de beneficios.
O(n log n)
O(n log n)
O(n2)
O(n3) (DIJSKTRA)
O(n2)
O(n2) (KRUSK/PRIM)
Libro Notas
SI
SI
SI
SI
SI
Ejemplo:
t1=5, t2=10 y t3=3
Sol: 3 + (3 + 5 ) + (3 + 5 + 10) = 29
SI
SI
SI
SI
SI
SI
SI
NO
NO
NO
NO
NO
Nombre Descripción
Mergesort
Mergesort
Un tromino es na figura geométrica compuesta por 3 cuadrados de
tamaño 1x1, en forma de L.
Objetivo: rellenar la cuadrícula de trominos sin solaparlos y
cubriéndola totalmente salvo la casilla marcada.
Pasos: dividir en 4 partes el panel y colocar un tromino solapado co
nlos cuadrantes sin la casilla marcada, utilizando las partes del
tromino como casillas marcadas en la nueva uteración.
caso base: cuadrante de 2x2 con una casilla marcada.
Quicksort
Proceso:
* Toma un elemento cualquiera del vector denominado pivote. Puede
ser el primero, o n/2
* Toma los valores del vector que sin menores que el pivote y forma
un subvector, e igual con los valores mayores o iguales. Una forma de
recorrer de izqda a dcha hasta encontrar un elemento mayor que el
pivote y de decha a izq hasta encontrar uno menor, e intercambiarlas,
deteniéndonos al cruzarnos.
* Se invoca recursivamente al algoritmo para cada subvector
Descomposición: no trivial
Combinación: trivial
Liga de equipos
Liga de equipos
2k equipos creao una liga con las siguientes condiciones:
* cada equipo puede jugar un partido al día
* la liga debe celebrarse en n-1 días
* se dispone de suficientes campos de juego
Elementos:
* Caso trivial: solo dos equipos ei y ej juegan en n-1 = 2-1=1 días (el
primero) → T[i,j]=d
* Descomponer:
* si el rango inicial es [1..n], la partición sería [1..n/2] y [n/2+1..n]
* generalizando: con [i..j] y m = (i+j-1)/2 la partición es [i..m] y
[m+1..j]
* Combinar:
* suponemos que los conjuntos de equipos cA={e1,...,en/2} y
cB={en/2+1,...,en} han jugado ya todos entre sí en los primeros n/2-1 días
* los equipos de cA y cB deben jugar en los n/2 días restantes,
Elementos:
empezando el día n/2 jugando e1 con en/2+1, e2 con en/2+2,...,en/2 con en/2+1
*y Caso trivial: realiza el skyline de un edificio
así sucesivamente.
* Descomponer:
* El conjunto de edificios se divide en dos mitades iguales
* Combinar:
* la entrada a este algoritmo son dos soluciones (2 líneas de
horizonte) y se fusionan eligiendo la mayor ordenada para cada bcisa
donde haya edificios
Estructura de datos:
Skyline de ciudad * Edificios: triadas del tipo e1=(x1, x2, h)(inicio, final, altura)
* TipoSkyline: concatenación de posiciones y alturas en esas
posiciones, s=(x1,h1,x2,h2,...,xk,hk) en donde cada par xi, hj represnta
transiciones entre un edificio y otro, o bien entre un edificio y la línea
de horizonte.
Skyline de ciudad
fun Quicksort(T[i..j])
var
l: natural
fvar
si trivial(j-i) entonces
Insertar(T[i..j])
sino
Pivotar(T[i..j],l)
Quicksort(T[i..l-1])
Quicksort(T[l+1..j])
fsi
ffun
fun Pivotar(T: vector[i..j] de entero, pivote: natural): booleano Quicksort: ϴ(n) + pivotar ϴ(n) → ϴ(n2)
var Utilizando la mediana del vector como
p,k: entero pivote → ϴ(n log n)
fvar
p ← T[i]
k←i
l←j+1
repetir
k←k+1
hasta T[k] > p V k ≥ j SI
repetir
l←l-1
hasta T[l] ≤ p
mientras k < l hacer
intercambiar(T,k,l)
repetir
k←k+1
hasta T[k] > p V k ≥ j
repetir
l←l-1
hasta T[l] ≤ p
fmientras
intercambiar(T,i,l)
pivote ← l
ffun
fun Mayoritario(i, j: natural, v:vector [1..n] de natural): entero
var
m:natural
s¡ ,s2:entero
fvar
si i = j entonces
dev v[i]
sino
m ← (i+ j) div 2
s1 ← Mayoritario(i, m, v)
s2 ← Mayoritario(m + 1, j, v)
dev Combinar(s1 , s2 , v)
ffun
ϴ(n2)
Progresión geométrica
a→2
b→2
k→2
fun Combinar(i,j,d: natural)
var
m,n,s,t: natural
fvar
m ← (i+j-1)/2 SI
n ← j-i+1
para s ← 0 hasta n/2-1 hacer
para s ← 0 hasta n/2-1 hacer
a ← i+t
b ← m+1+((t+s) mod (n/2))
fpara
fpara
ffun
ϴ(log n) NO
ϴ(n log n) (n=fil x col) NO
ϴ(n) NO
ϴ(2n) NO
ϴ(log n) NO
Notas
Nombre Descripción
Fibonacci
Definición:
Coeficientes binomiales
* Con N tipos de monedas (imposible con algoritmo voraz)
* Construcción de la tabla:
Cambio de monedas + T[i,j]= Nº de monedas de tipo xi o menos, para cantidad Cj
* Posibilidad de usar un algoritmo voraz ϴ(C) para saber las monedas usadas.
T: Tabla de precios
C: Tabla de costes mínimos
* Objetos: X1…Xn
* Volumenes: V1…Vn
* Beneficios: b1..bn
* M[i,j] → beneficio de llenar una mochila de volumen j con objetos desde X1 a Xi
Mochila NO
FRACCIONABLE (pesos
naturales)
𝑚𝑎𝑥𝑖𝑚𝑖𝑧𝑎𝑟∑_(𝑖=0)^𝑛▒ 〖𝑥 _𝑖 𝑏_𝑖 〗 𝑐𝑢𝑚𝑝𝑙𝑖𝑒𝑛𝑑𝑜 ∑ _(𝑖=0)^𝑛▒ 〖𝑥 _𝑖 𝑏_𝑖 〗≤𝑉
Mochila NO
FRACCIONABLE (pesos
naturales)
* Ecuación de recurrencia:
di → nº de columnas de la matriz Mi(num de filas será di-1)
E(i,j) → nº mínimo de productos escalares para multiplicar las matrices Mi..Mj
Multiplicación de matrices
Multiplicación de matrices
* Algoritmo de Floyd, como alternativa al algoritmo de Dijkstra.
* M(i,j,k) → Coste mínimo entre los nodos i y j pudiendo pasar por los nodos entre 1 y k
* A[i,j] → el coste de la arista entre i y j
* Para calcular M(i,j,k) solo necesitamos los datos tras incluir el nodo k-1, así que utilizamos una tabla
NxN que se va reescribiendo
* Ecuación de recurrencia:
* Definimos C(i,j):
* Número mínimo de cambios para transformar X (hasta la posición i) en Y (hasta la posición j)
* Si j=0 → hay que hacer i borrados
* Si i=0 → hay que hacer j inserciones
* Si son mayores que 0:
* Si borramos Xi → C(i,j) = 1 + C(i-1,j)
* Si insertamos Yj → C(i,j) = 1 + C(i,j-1)
* Si transformamos Xi en Yj
* Xi ≠ Yj → C(i,j) = 1 + C(i-1, j-1)
Distancia de edición
* Xi = Yj → C(i,j) = C(i-1, j-1)
* Ecuación de recurrencia:
fun MinMultiple2(T,C: tabla; i,j: entero, var minimo: entero; var emb: entero): entero
var
k: entero
fvar
minimo ← ∞
emb ← 1
para k ← i+1 hasta j hacer
si C[k,j] + T[j,k] < minimo entonces
minimo ← C[k,j] + T[i,k]
emb ← k
fsi
fpara
dev minimo
ffun
tipo Tabla = matriz[0..n, 0..V] de entero
tipo Vector = matriz[0..n] de entero
fun MochilaEntera(vol,ben:Vector; n,V:entero;M:Tabla)
var
i,j: entero
fvar
para i ← 1 hasta n hacer
M[i,0] ← 0
fpara
para j ← 1 hasta V hacer
M[i,0] ← 0
fpara
para j ← j+1 hasta n hacer
para i ← i+1 hasta n hacer
si vol[i] > j entonces
M[i,j] ← M[i-1,j]
sino
ϴ(nV) Si
M[i,j] ← max(M[i-1,j], M[i-1,j-vol[i]] + ben[i])
fsi
𝑏_𝑖+𝑚𝑜𝑐ℎ𝑖𝑙𝑎(𝑖−1,𝑊−𝑣_𝑖fpara)}, 𝑠𝑖 𝑖>0 𝑦 𝑣_𝑖≤𝑊)┤
fpara
ffun
Si
Si
tipo Trans=
registro
ope: Vector[1..30] de caracter
fregistro
fun IdentificarTrans(X:Vector[1..n] de caracter, Y: Vector[1..m] de caracter; n,m:entero; C:Tabla;
transformada: Vector[1..nm] de Trans)
var
i,j,k: entero
fvar
i←n
j←m
k ← C[n,m]
mientras k > 0 hacer
caso de
C[i,j] = C[i-1,j]+1 hacer
transforma[k].ope ← "borrado" ϴ(nm)
transforma[k].pos ← j+1
k←k-1
i←i-1
C[i,j] = C[i,j-1]+1 hacer
transforma[k].ope ← "insercion"
transforma[k].pos ← j
transforma[k].car ← Y[j]
k←k-1
j←j-1
C[i,j] = C[i-1,j-1]+1 hacer
transforma[k].ope ← "sustitucion"
transforma[k].pos ← j
transforma[k].car ← Y[j]
k←k-1
i←i-1
j←j-1
C[i,j] = C[i-1,j-1] hacer
i←i-1
j←j-1
fcaso
fmientras
ffun
Notas
Nombre Descripción
• Colocar N reinas en un tablero de ajedrez NxN de forma que
ninguna reina ataque a otra
• La columna de la reina ci va a ser i, y la solución es una
asignación de la fila que corresonde a cada reina(un vector donde
fi es la fila asignada a ci)
Tablero de reinas
Tablero de reinas
Coloreado de grafos
Coloreado de grafos
• Definición: caminos que pasan por cada vértice una sola vez y
terminan en el vértice inicial.
• Objetivo: encontrar todos los ciclos hamiltonianos de un grafo.
Ciclos Hamiltonianos
Ciclos Hamiltonianos
Reparto equitativo
Reparto equitativo
Donde:
s → vector que almacena la solución
n → tamaño del tablero
k → siguiente reina a colocar
Donde:
v → vector de soluciones donde v[i]=j es el color j asignado al nodo i
n → num. nodos
m → num de colores
Donde:
edificio → matriz de casillas por donde movernos
casilla → posición actual
exploradas → matriz donde marcamos por donde pasamos
solución → lista de casillas con el recorrido
Viajante de comercio
Viajante de comercio
fun EstimacionOpt(pesos, valores: TVectorR; P: real; k: entero, pesoT: real; valorT: real): real
var
capacidad, estimación: real
i: entero
fvar
capacidad ← P - pesoT
estimacion ← valorT
i←k+1
mientras i ≤ n ˄ capacidad ≥ 0 entonces
si pesos[i] ≤ capacidad entonces
estimacion ← estimacion + valor[i]
capacidad ← capacidad - pesos[i]
sino
estimacion ← estimacion + (capacidad / pesos[i])*valor[i]
capacidad ← 0
fsi
i ← i +1
fmientras
dev estimacion
ffun
fun EstimacionPes(pesos, valores: TVectorR; P: real; k: entero, pesoT: real; valorT: real): real
var
capacidad, estimación: real
i: entero
fvar
capacidad ← P - pesoT
estimacion ← valorT
i←k+1
mientras i ≤ n ˄ capacidad ≥ 0 entonces
si pesos[i] ≤ capacidad entonces
cota ← cota + valor[i]
capacidad ← capacidad - pesos[i]
fsi
i ← i +1
fmientras
dev cota
ffun
nodo, hijo: TNodo
cota, estPes: real
fvar
monticulo ← CrearMonticuloVacio()
costeT ← 0
{Construimos el primer nodo}
nodo.pasteleros ← pasteleros
para i ← 1 hasta n hacer
nodo.asignados[i] ← falso
fpara
nodo.k ← 0
nodo.costeT ← 0
nodo.estOpt ← EstimacionOpt(costes, pedido, nodo.k, nodo.costeT)
Insertar(nodo, monticulo)
cota ← EstimacionPes(costes, pedido, nodo.k, nodo.costeT)
mientras ¬ MonticuloVacio?(monticulo) Λ EstimacionOpt(Primero(monticulo)) ≤ cota hacer
nodo ← ObtenerCima(monticulo)
{se generan las extensiones válidas del nodo }
{para cada pastelero no asignado se crea un nodo}
hijo.k ← nodo.k + 1
hijo.pasteleros ← nodo.pasteleros
hijo.asignados ← nodo.asignados
para i ← 1 hasta n hacer
si ¬hijo.asignados[i] entonces
hijo.pasteleros[hijo.k] ← i
hijos.asignados[i] ← cierto
hijo.costeT ← nodo.costeT + coste[i.pedido[hijo.k]]
si hijo.k = n entonces
si costeT ≥ hijo.costeT entonces
pasteleros ← hijo.pasteleros
costeT ← costeT.valorT
cota ← costeT
fsi
sino {la solución no está completa}
hijo.estOpt ← EstimacionOpt(costes, pedido, hijo.k, hijo.costeT)
Insertar(hijo, monticulo)
estPes ← EstimacionPes(costes, pedido, hijo.k, hijo.costeT)
si cota > estPes entonces
cota ← estPes
fsi
fsi
hijo.asignados[i] ← falso {se desmarca}
fsi
fpara
fmientras
ffun
minArista ← menorArista()
costeT ← ∞
{Construimos el primer nodo}
nodo.ruta ← ruta
nodo.asignados[1] ← cierto
para i ← 2 hasta n hacer
nodo.asignado[i] ← falso
fpara
nodo.k ← 1
nodo.costeT ← 0
nodo.estOpt ← EstimacionOpt(grafo, minArista, nodo.k, nodo.costeT)
Insertar(nodo, monticulo)
cota ← ∞
mientras ¬ MonticuloVacio?(monticulo) Λ EstimacionOpt(Primero(monticulo)) ≤ cota hacer
nodo ← ObtenerCima(monticulo)
{se generan las extensiones válidas del nodo }
verticeAnt ← nodo.ruta[nodo.k]
hijo.k ← nodo.k + 1
hijo.ruta ← nodo.ruta
hijo.asignados ← nodo.asignados
para i ← 2 hasta n hacer
si ¬hijo.asignados[i] Λ grafo[verticeAnt, i] ≠ ∞ entonces
hijo.ruta[hijo.k] ← i
hijos.asignados[i] ← cierto
hijo.costeT ← nodo.costeT + grafo[verticeAnt,i]
si hijo.k = n entonces
si grafo[i, 1] ≠ ∞ entonces
hijo.costeT ← hijo.costeT + grafo[i,1]
si costeT ≥ hijo.costeT entonces
ruta ← hijo.ruta
costeT ← hijo.costeT
cota ← costeT
fsi
fsi
sino {la solución no está completa}
hijo.estOpt ← EstimacionOpt(grafo, minArista, hijo.k, hijo.costeT)
si hijo.estOpt < costeT entonces
Insertar(hijo, monticulo)
fsi
fsi
hijo.asignados[i] ← falso {se desmarca}
fsi
fpara
fmientras
ffun
O(2n)
SI
O(n!)
SI
O(n!)
SI
O(2n)
SI
O(3m)
SI