Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Alberto Verdejo Dpto. de Sistemas Informticos y Computacin a o Universidad Complutense de Madrid Noviembre 2010
MTP 2010-2011
1 / 51
Programacin dinmica o a
Bibliograf a
R. Neapolitan y K. Naimipour. Foundations of Algorithms using C++ pseudocode. Tercera edicin. Jones and Bartlett Publishers, 2004. o Cap tulo 3 E. Horowitz, S. Sahni y S. Rajasekaran. Computer Algorithms. Tercera edicin. Computer Science Press, 1998. o Cap tulo 5 N. Mart Oliet, Y. Ortega Malln y J. A. Verdejo Lpez. Estructuras de e o datos y mtodos algor e tmicos: ejercicios resueltos. Coleccin Prentice o Practica, Pearson/Prentice Hall, 2003. Cap tulo 13
MTP 2010-2011
2 / 51
Programacin dinmica o a
Motivacin o
n r
1 1 (n1 ) + (n1) r r
si r = 0 r = n si 0 < r < n
6 4
5 3 4 2 3 1 2 0 1 0 2 1 1 1 1 0 2 1 1 1 3 2 2 2 1 0 2 1 1 1 3 2 2 2 1 0 4 3 3 3 2 1 1 1 3 2 2 2 4 3
5 4 4 4 3 3
MTP 2010-2011
3 / 51
Programacin dinmica o a
Programacin dinmica o a
Mtodo ascendente e
Comenzar por resolver todos los subproblemas ms pequeos que se puedan a n necesitar, para ir combinndolos hasta llegar a resolver el problema original. a
(0) 0 ( 1) (1 ) 1 0 (2 ) ( 2 ) ( 2) 0 1 2 ( 3) ( 3) (3 ) (3 ) 0 1 2 3 . . .. . .. . .
La base de la programacin dinmica es el uso de una tabla para ir o a almacenando los resultados correspondientes a instancias ms sencillas del a problema a resolver.
MTP 2010-2011
5 / 51
Programacin dinmica o a
Identicacin o
Especicacin de la funcin que representa el problema a resolver. o o Determinacin de las ecuaciones recurrentes para calcular dicha o
funcin. o Comprobacin del alto coste de clculo de dicha funcin debido a o a o la repeticin de subproblemas a resolver. o Construccin o
Sustitucin de la funcin por una tabla. o o Inicializacin de la tabla segn los casos base de la denicin o u o
recursiva de la funcin. o Sustitucin, en las ecuaciones, de las llamadas recursivas por o consultas a la tabla. Planicacin del orden de llenado de la tabla, de forma que se o respeten las necesidades de cada entrada de la tabla. Posible optimizacin en espacio. o
MTP 2010-2011
6 / 51
Programacin dinmica o a
Nmeros combinatorios u
0 1 2 . . . n
0 1 1 1 . . . 1
1 0 1 2 . . . n
2 0 0 1 . . . (n ) 2
r 0 0 0 . . . (n) r
fun pascal (n, r : nat ) dev c : nat var C[0..n, 0..r] de nat C[0, 0] : = 1 C[0, 1..r] : = [0] para i = 1 hasta n hacer C[i, 0] : = 1 para j = 1 hasta r hacer C[i, j] : = C[i 1, j 1] + C[i 1, j] fpara fpara c : = C[n, r] un
MTP 2010-2011
7 / 51
Programacin dinmica o a
fun pascal2(n, r : nat ) dev c : nat var C[0..r] de nat C[0] : = 1 ; C[1..r] : = [0] para i = 1 hasta n hacer para j = r hasta 1 paso 1 hacer C [ j ] : = C [ j ] + C [ j 1] fpara fpara c : = C[ r] un
Alberto Verdejo (UCM) MTP 2010-2011 8 / 51
Programacin dinmica o a
El campeonato mundial
Competicin entre dos equipos, A y B, en la que el ganador es el primer o
equipo que consiga n victorias. No hay empates, los resultados de todos los partidos son independientes, y para cualquier partido dado hay una probabilidad constante p de que lo gane el equipo A (y por tanto una probabilidad constante q = 1 p de que lo gane el equipo B). Queremos calcular la probabilidad que tiene el equipo A de ganar la competicin, antes del primer partido. o Denimos la funcin o P(i, j) = probabilidad de que A gane la competicin si a A le faltan o i victorias para ganar y a B le faltan j victorias.
El valor que nos interesa calcular es P(n, n). Denicin recursiva: o P(i, j) = pP(i 1, j) + qP(i, j 1) Los casos bsicos son a P(0, j) P(i, 0)
Alberto Verdejo (UCM)
= =
1 0
1jn 1in
9 / 51
MTP 2010-2011
Programacin dinmica o a
fun competicin (n : nat+ , p : real ) dev probabilidad-A : real o var P[0..n, 0..n] de real P[0, 1..n] : = [1] P[1..n, 0] : = [0] para i = 1 hasta n hacer para j = 1 hasta n hacer P[i, j] : = p P[i 1, j] + (1 p) P[i, j 1] fpara fpara probabilidad-A : = P[n, n] un
{ ( n2 ) }
MTP 2010-2011
10 / 51
Programacin dinmica o a
Rellenar de izquierda a derecha. fun competicin2 (n : nat+ , p : real ) dev probabilidad-A : real o var P[0..n] de real P [ 0] : = 0 P[1..n] : = [1] para i = 1 hasta n hacer para j = 1 hasta n hacer P [ j ] : = p P [ j ] + (1 p) P [ j 1] fpara fpara probabilidad-A : = P[n] un
{ (n ) }
MTP 2010-2011
11 / 51
Programacin dinmica o a
MTP 2010-2011
12 / 51
Programacin dinmica o a
Existe una cantidad ilimitada de monedas de cada valor. Se quiere pagar una cantidad C > 0 utilizando el menor nmero posible de u
monedas. monedas(n, C) = nmero m u nimo de monedas para pagar la cantidad C considerando los tipos de monedas del 1 al n.
u Se cumple el principio de optimalidad de Bellman segn el cual para conseguir una solucin ptima basta considerar subsoluciones ptimas. o o o
MTP 2010-2011
13 / 51
Programacin dinmica o a
si mi > j si mi j
= =
0 +
j
0in 1jC
C
j mi
MTP 2010-2011
14 / 51
Programacin dinmica o a
fun devolver-cambio1 (M[1..n] de nat+ , C : nat ) dev numero : nat { numero es la cantidad de monedas en la solucin ptima } o o { numero es + cuando no existe solucin } o var monedas[0..n, 0..C] de nat { inicializacin } o monedas[0, 1..C] : = [+ ] monedas[0..n, 0] : = [0] { rellenar la matriz } para i = 1 hasta n hacer para j = 1 hasta C hacer si M[i] > j entonces monedas[i, j] : = monedas[i 1, j] si no monedas[i, j] : = mn(monedas[i 1, j], monedas[i, j M[i]] + 1) fsi fpara fpara numero : = monedas[n, C] un Coste: (nC) tanto en tiempo como en espacio adicional.
MTP 2010-2011
15 / 51
Programacin dinmica o a
C = 8, n = 3, m1 = 1, m2 = 4 y m3 = 6. 0 0 0 0 0 1 + 1 1 1 2 + 2 2 2 3 + 3 3 3 4 + 4 1 1 5 + 5 2 2 6 + 6 3 1 7 + 7 4 2 8 + 8 2 2
0 1 2 3
MTP 2010-2011
16 / 51
Programacin dinmica o a
Por tanto, sabemos que si monedas(i, j) = monedas(i 1, j) es porque podemos no coger ninguna moneda de tipo i para pagar la cantidad j, mientras que si monedas(i, j) = monedas(i 1, j) debemos coger al menos una moneda de tipo i para pagar la cantidad j.
MTP 2010-2011
17 / 51
Programacin dinmica o a
{ monedas[n, C] = + } fun calcular-monedas1 (M[1..n] de nat+ , monedas[0..n, 0..C] de nat ) dev cu ntas[1..n] de nat a { cu ntas[i] es el nmero de monedas de tipo i cogidas } a u cu ntas[1..n] : = [0] a i := n ; j := C mientras j > 0 hacer { no hemos pagado todo } si M[i] j monedas[i, j] = monedas[i 1, j] entonces { tomamos una moneda de tipo i } cu ntas[i] : = cu ntas[i] + 1 a a j : = j M[ i ] si no { no tomamos ms monedas de tipo i } a i := i 1 fsi fmientras un
{ (C ) }
MTP 2010-2011
18 / 51
Programacin dinmica o a
fun devolver-cambio2 (M[1..n] de nat+ , C : nat ) dev numero : nat var monedas[0..C] de nat { inicializacin } o monedas[0] : = 0 monedas[1..C] : = [+ ] { hacer las actualizaciones } para i = 1 hasta n hacer para j = M[i] hasta C hacer monedas[j] : = mn(monedas[j], monedas[j M[i]] + 1) fpara fpara numero : = monedas[C] un Coste: (nC) en tiempo y (C) en espacio adicional.
Alberto Verdejo (UCM) MTP 2010-2011 19 / 51
Programacin dinmica o a
Podemos optimizar en espacio y seguir calculando la solucin ptima? o o La ultima la contiene la informacin sobre el nmero de monedas m o u nimo para cada cantidad, con el sistema monetario completo. Si monedas(n, j) = monedas(n, j mi ) + 1 para algn j y algn i, sabemos que podemos coger una moneda de tipo i para u u conseguir una solucin ptima para pagar j. o o Adems, como el nmero de monedas de cada tipo es ilimitado, el sistema a u monetario no cambia y se puede iterar el proceso para j mi haciendo comparaciones de nuevo en la ultima la, es decir, el vector. Para implementar este proceso, al principio j vale C e i vale n; la cantidad j decrece tal y como se van cogiendo monedas y, cuando la ecuacin anterior no o es cierta y por tanto no se puede coger ninguna moneda ms de tipo i, se a decrementa i pasando a considerar el tipo de moneda anterior i 1.
MTP 2010-2011
20 / 51
Programacin dinmica o a
{ monedas[C] = + } fun calcular-monedas2 (M[1..n] de nat+ , monedas[0..C] de nat ) { (C ) } dev cu ntas[1..n] de nat a { cu ntas[i] es el nmero de monedas de tipo i cogidas } a u cu ntas[1..n] : = [0] a i := n ; j := C mientras j > 0 hacer { no hemos pagado todo } si M[i] j c monedas[j] = monedas[j M[i]] + 1 entonces { tomamos una moneda de tipo i } cu ntas[i] : = cu ntas[i] + 1 a a j : = j M[i] si no { no tomamos ms monedas de tipo i } a i := i 1 fsi fmientras un
MTP 2010-2011
21 / 51
Programacin dinmica o a
Cuando Al -Bab consigue por n entrar en la Cueva de los Cuarenta a Ladrones encuentra all gran cantidad de objetos muy valiosos. A pesar de su pobreza, Al -Bab conoce muy bien el peso y valor de a cada uno de los objetos en la cueva. Debido a los peligros que tiene que afrontar en su camino de vuelta, solo puede llevar consigo aquellas riquezas que quepan en su pequea n mochila, que soporta un peso mximo conocido. a Suponiendo que los objetos no se pueden fraccionar y que los pesos son nmeros naturales positivos, determinar qu objetos debe elegir u e Al -Bab para maximizar el valor total de lo que pueda llevarse en su a mochila.
MTP 2010-2011
22 / 51
Programacin dinmica o a
En la cueva hay n objetos, cada uno con un peso (natural) pi > 0 y un valor (real) vi > 0 para todo i entre 1 y n. La mochila soporta un peso total (natural) mximo M > 0. a El problema consiste en maximizar
xi vi
i=1
con la restriccin o
xi pi M,
i=1
MTP 2010-2011
23 / 51
Programacin dinmica o a
Denimos una funcin o mochila(i, j) = mximo valor que podemos poner en la mochila de a peso mximo j considerando los objetos del 1 al i. a
si pi > j si pi j
con 1 i n y 1 j M. Los casos bsicos son: a mochila(0, j) mochila(i, 0) Problema inicial: mochila(n, M).
= =
0 0
0jM 0 i n.
MTP 2010-2011
24 / 51
Programacin dinmica o a
mochila 0 1 i1 i n
j pi
Recorrer la matriz por las de arriba abajo y cada la de izquierda a derecha. Si solo quisiramos el valor mximo alcanzable, podr e a amos optimizar el espacio adicional utilizando solo un vector que recorrer amos de derecha a izquierda. Si queremos devolver los objetos que forman parte de la solucin optima no o interesa optimizar, porque en ese caso las comparaciones que hacemos para llenar una posicin siempre se reeren a posiciones de la la anterior: o mochila(i, j) = m x{mochila(i 1, j), mochila(i 1, j pi ) + vi } a
no cogemos el objeto i s cogemos el objeto i
MTP 2010-2011
25 / 51
Programacin dinmica o a
fun mochila-pd (P[1..n] de nat+ , V [1..n] de real + , M : nat+ ) dev valor : real, cu les[1..n] de 0..1 a { cu les[i] indica si hemos cogido o no el objeto i } a var mochila[0..n, 0..M] de real { inicializacin } o mochila[0..n, 0] : = [0] mochila[0, 1..M] : = [0] { rellenar la matriz } para i = 1 hasta n hacer para j = 1 hasta M hacer si P[i] > j entonces mochila[i, j] : = mochila[i 1, j] si no mochila[i, j] : = mx(mochila[i 1, j], mochila[i 1, j P[i]] + V [i]) a fsi fpara fpara valor : = mochila[n, M]
MTP 2010-2011
26 / 51
Programacin dinmica o a
{ clculo de los objetos } a resto : = M para i = n hasta 1 paso 1 hacer si mochila[i, resto] = mochila[i 1, resto] entonces cu les[i] : = 0 a si no { s coger objeto i } cu les[i] : = 1 ; resto : = resto P[i] a fsi fpara un
Coste: (nM) tanto en tiempo como en espacio adicional.
{ no coger objeto i }
MTP 2010-2011
27 / 51
Programacin dinmica o a
El pa de Fanfanisn emite n sellos diferentes de valores naturales s a positivos s1 , s2 , . . . , sn . Se quiere enviar una carta y se sabe que la correspondiente tarifa postal es T. De cuntas formas diferentes se puede franquear exactamente la a carta, si el orden de los sellos no importa?
formas(n, T )
MTP 2010-2011
28 / 51
Programacin dinmica o a
formas(i, j)
si si > j si si j
MTP 2010-2011
29 / 51
Programacin dinmica o a
fun sellos(S[1..n] de nat+ , T : nat+ ) dev num-formas : nat var formas[0..T ] de nat { inicializacin } o formas[0] : = 1 formas[1..T ] : = [0] { actualizaciones del vector } para i = 1 hasta n hacer para j = S[i] hasta T hacer formas[j] : = formas[j] + formas[j S[i]] fpara fpara num-formas : = formas[T ] un Coste: (nT ) en tiempo y (T ) en espacio adicional.
MTP 2010-2011
30 / 51
Programacin dinmica o a
El Maqui y el Popeye acaban de desvalijar la reserva nacional de oro. Los lingotes estn empaquetados en n cajas de diferentes pesos a naturales positivos pi para i entre 1 y n. Como no tienen tiempo de desempaquetarlos para dividir el bot n, deciden utilizar los pesos de cada una de las cajas para distribuir el bot a medias. n Al cabo de un buen rato todav no han conseguido repartirse el bot a n, por lo cual acuden al Teclas para saber si el bot se puede dividir en n dos partes iguales sin desempaquetar las cajas con los lingotes.
MTP 2010-2011
31 / 51
Programacin dinmica o a
Considerando P = n 1 pi , el problema es equivalente a comprobar si es i= posible, sumando algunos de los pesos, obtener P/2.
se-puede(i, j)
booleano que indica si es posible sumar la cantidad j eligiendo algunas de las i primeras cajas.
se-puede(i, j)
si pi > j si pi j
= =
falso cierto
1 j P/2 0 i n.
MTP 2010-2011
32 / 51
Programacin dinmica o a
Utilizamos una matriz se-puede[0..n, 0..P/2] para calcular los valores de la recurrencia. Si solo queremos saber si se puede o no sumar la cantidad P/2, y no los objetos necesarios para sumar tal cantidad, podemos optimizar el espacio adicional utilizando solo un vector, se-puede[0..P/2]. Ya que las dos posiciones necesarias para calcular se-puede(i, j) se encuentran en la la anterior,
i1 i j
el vector tiene que recorrerse de derecha a izquierda, para no perder valores de la la anterior que se necesitan despus. e
MTP 2010-2011
33 / 51
Programacin dinmica o a
{ P = P/2 } fun repartir-botn-par-pd (peso[1..n] de nat+ , P : nat+ ) dev respuesta : bool var se-puede[0..P ] de bool { inicializacin } o se-puede[0] : = cierto se-puede[1..P ] : = [falso] { actualizaciones del vector } para i = 1 hasta n hacer para j = P hasta peso[i] paso 1 hacer se-puede[j] : = se-puede[j] se-puede[j peso[i]] fpara fpara respuesta : = se-puede[P ] un { P = n=1 peso[i] } i fun repartir-botn-pd (peso[1..n] de nat+ , P : nat+ ) dev respuesta : bool si impar(P) entonces respuesta : = falso si no respuesta : = repartir-botn-par-pd (peso, P div 2) fsi un
Alberto Verdejo (UCM) MTP 2010-2011 34 / 51
Programacin dinmica o a
Denicin de la funcin o o
La recurrencia, con 1 k, i, j n, es Ck (i, j) = mn{Ck1 (i, j), Ck1 (i, k) + Ck1 (k, j)}. El caso bsico se presenta cuando k = 0: a C0 (i, j) = G[i, j] 0 si i = j si i = j
Programacin dinmica o a
En principio necesitamos n + 1 matrices n n, con un espacio adicional en (n3 ). Pero se puede mejorar. Para calcular la matriz Ck solo necesitamos la matriz Ck1 y las actualizaciones se pueden ir realizando sobre la misma matriz.
k k j j
Ck 1
Ck
Pero la la k y la columna k no cambian cuando actualizamos de Ck1 a Ck . Para la la k tenemos Ck (k, j) = mn{Ck1 (k, j), Ck1 (k, k) + Ck1 (k, j)} = Ck1 (k, j), ya que Ck1 (k, k) = 0. Y de igual forma Ck (i, k) = Ck1 (i, k) para la columna k. Solo utilizamos una matriz C[1..n, 1..n], en la que nalmente se devuelve la solucin, de modo que el coste en espacio adicional est en (1). o a
Alberto Verdejo (UCM) MTP 2010-2011 36 / 51
Programacin dinmica o a
fun Floyd(G : grafo-val[ n] ) dev C[1..n, 1..n] de real , camino[1..n, 1..n] de 0..n { inicializacin } o C : = G ; camino[1..n, 1..n] : = [0] para i = 1 hasta n hacer C[i, i] : = 0 fpara { actualizaciones de la matriz } para k = 1 hasta n hacer para i = 1 hasta n hacer para j = 1 hasta n hacer temp : = C[i, k] + C[k, j] si temp < C[i, j] entonces C[i, j] : = temp camino[i, j] : = k fsi fpara fpara fpara un Coste: (n3 ) en tiempo y (1) en espacio adicional.
MTP 2010-2011
37 / 51
Programacin dinmica o a
proc imprimir-caminos (e C[1..n, 1..n] de real , e camino[1..n, 1..n] de 0..n) para i = 1 hasta n hacer para j = 1 hasta n hacer si C[i, j] < + entonces imprimir(camino de, i, a, j) imprimir(i) ; imp-camino-int (i, j, camino) ; imprimir (j) fsi fpara fpara fproc proc imp-camino-int (e i, j : 1..n, e camino[1..n, 1..n] de 0..n) k : = camino[i, j] si k > 0 entonces { hay un camino no directo } imp-camino-int (i, k, camino) ; imprimir(k) ; imp-camino-int (k, j, camino) fsi fproc
MTP 2010-2011
38 / 51
Programacin dinmica o a
cij =
aik bkj .
k=1
Se necesitan pqr multiplicaciones entre escalares para calcular C. Para multiplicar una secuencia de matrices M1 M2 Mn (Mi tiene dimensiones di1 di ) el orden de las matrices no se puede alterar pero s el de los productos a realizar, ya que la multiplicacin de matrices es asociativa. o Cul es la mejor forma de insertar parntesis en la secuencia de matrices de a e forma que el nmero total de multiplicaciones entre escalares sea m u nimo? Ejemplo: A135 , B589 , C893 , D334
((A B) C) D
5785 3471 1326
Alberto Verdejo (UCM)
10582
(A (B C ) ) D
1335 195 1326
2856
MTP 2010-2011
39 / 51
Programacin dinmica o a
( M1 . . . Mk ) ( Mk + 1 . . . Mn )
d0 dk dk dn
Utilizamos la funcin o matrices(i, j) = nmero m u nimo de multiplicaciones escalares para realizar el producto matricial Mi Mj .
La recurrencia solo tiene sentido cuando i j. El caso recursivo, i < j, se dene de la siguiente manera: matrices(i, j)
ik j1
El caso bsico se presenta cuando solo tenemos una matriz, esto es, i = j: a matrices(i, i) = 0. Problema inicial: matrices(1, n).
MTP 2010-2011
40 / 51
Programacin dinmica o a
Utilizaremos una tabla matrices[1..n, 1..n], de la cual solo necesitaremos la mitad superior por encima de la diagonal principal.
matrices i j
... . . .
MTP 2010-2011
41 / 51
Programacin dinmica o a
matrices 1 2 3 4 5 6 7 8
d = 7 (n 7 = 1 elemento) . ..
d=2 d = 1 (n 1 = 7 elementos)
Las diagonales se numeran desde d = 1 hasta d = n 1 en el orden en el que tienen que recorrerse. Cada diagonal tiene n d elementos que numeraremos del i = 1 al i = n d. As este ndice nos sirve directamente para conocer la la en la que se encuentra el elemento por el que vamos. La columna podemos calcularla mediante j = i + d.
MTP 2010-2011
42 / 51
Programacin dinmica o a
fun multiplica-matrices (D[0..n] de nat+ ) dev num-mn : nat, P[1..n, 1..n] de 0..n var matrices[1..n, 1..n] de nat para i = 1 hasta n hacer { inicializacin, diagonal principal } o matrices[i, i] : = 0 ; P[i, i] : = 0 fpara { recorrido por diagonales } para d = 1 hasta n 1 hacer { recorre diagonales } para i = 1 hasta n d hacer { recorre elementos dentro de la diagonal } j := i + d { calcular m nimo } matrices[i, j] : = + para k = i hasta j 1 hacer temp : = matrices[i, k] + matrices[k + 1, j] + D[i 1] D[k] D[j] si temp < matrices[i, j] entonces matrices[i, j] : = temp ; P[i, j] : = k fsi fpara fpara Coste: en tiempo (n3 ) fpara en espacio (n2 ) num-mn : = matrices[1, n] un
Alberto Verdejo (UCM) MTP 2010-2011 43 / 51
Programacin dinmica o a
{1ijn} proc escribir-parn (e i, j : nat, e P[1..n, 1..n] de nat ) e si i = j entonces imprimir (Mi ) si no k : = P[i, j] si k > i entonces imprimir (() ; escribir-parn (i, k, P) ; imprimir ()) e si no imprimir (Mi ) fsi imprimir (*) si k + 1 < j entonces imprimir(() ; escribir-parn (k + 1, j, P) ; imprimir ()) e si no imprimir (Mj ) fsi fsi fproc
MTP 2010-2011
44 / 51
Programacin dinmica o a
c2 = Isabel, p2 = 3 , 8
c3 = Rafa, 1 p3 = 8 ,
c4 = Teresa p4 = 1 8 Rafa
Isabel David
18 8
Teresa
MTP 2010-2011
45 / 51
Programacin dinmica o a
ck
c1 , . . . , ck1
ck+1 , . . . , cn
Consideremos un arbol de bsqueda a para las claves {c1 , . . . , cn } en el que la u clave ck est en la ra a z. Utilizamos la funcin o compa (1, n) = nmero medio de comparaciones para realizar una bsqueda u u en a en las condiciones del enunciado.
MTP 2010-2011
46 / 51
Programacin dinmica o a
compa (1, n)
= = = = =
pl nivela (cl )
l=1 k1
pk + pk + pk +
n
pl nivela (cl ) +
l=k +1
pl nivela (cl )
l=1 k1
pl (nivelhi(a) (cl ) + 1) + pl +
l=k +1
pl (nivelhd(a) (cl ) + 1)
l=1 k1
l=k +1
k1
pl +
pl nivelhi(a) (cl ) +
l=k +1
pl nivelhd(a) (cl )
l=1
l=1
l=1
MTP 2010-2011
47 / 51
Programacin dinmica o a
comp(i, j)
nmero medio m u nimo de comparaciones en un rbol a de bsqueda conteniendo las claves ci+1 , . . . , cj . u
El caso que nos interesa, para un arbol con n claves, ser comp(0, n): a comp (0, n)
l=1
comp(i, j)
l=i+1
MTP 2010-2011
48 / 51
Programacin dinmica o a
prob[i, j] =
l=i+1
pl ,
se puede calcular la matriz mediante la frmula o prob[i, j] = prob[i, j 1] + pj , teniendo como caso bsico prob[i, i] = 0. a Guardamos en una tercera matriz raz[0..n, 0..n] las decisiones sobre las ra ces de los rboles ptimos a o raz[i, j] ser la ra del rbol de bsqueda ptimo con las claves ci+1 , . . . , cj . a z a u o
MTP 2010-2011
49 / 51
Programacin dinmica o a
{ C [ 1 ] < < C [ n ] i : 1 i n : 0 P [ i] 1 } fun rbol-bsqueda-ptimo (C[1..n] de clave, P[1..n] de real ) a u o dev num-comp : real, raz[0..n, 0..n] de 0..n var comp[0..n, 0..n] de real , prob[0..n, 0..n] de real para i = 0 hasta n hacer comp[i, i] : = 0 ; prob[i, i] : = 0 ; raz[i, i] : = 0 fpara para d = 1 hasta n hacer { recorre diagonales } para i = 0 hasta n d hacer { recorre elementos dentro de la diagonal } j := i + d prob[i, j] : = prob [i, j 1] + P[j] { calcular m nimo } mnimo : = + para k = i + 1 hasta j hacer temp : = comp[i, k 1] + comp[k, j] si temp < mnimo entonces mnimo : = temp ; raz [i, j] : = k fsi fpara comp[i, j] : = mnimo + prob[i, j] fpara fpara Coste: en tiempo (n3 ) num-comp : = comp[0, n] en espacio (n2 ) un
MTP 2010-2011
50 / 51
Programacin dinmica o a
{ C [ 1] < < C [ n ] i j } fun construir-rbol (C[1..n] de clave, raz[0..n, 0..n] de 0..n, i, j : 0..n) a dev arbol : rbol-bb[clave] a var iz, dr : rbol-bb[clave] a si raz[i, j] = 0 entonces arbol : = abb-vaco () si no k : = raz[i, j] iz : = construir-rbol (C, raz, i, k 1) a dr : = construir-rbol (C, raz, k, j) a arbol : = plantar (iz, C[k], dr) fsi un
Llamada inicial construir-rbol (C, raz, 0, n). a Coste en tiempo: (n)
MTP 2010-2011
51 / 51