Vous êtes sur la page 1sur 26

ANLISIS DE

ALGORITMOS
Escuela Superior de Cmputo

Contenido
Introduccin
Programacin dinmica
Enfoques de la programacin dinmica
Principio de optimalidad
Diseo

de

un

algoritmo

de

programacin

dinmica
Ejemplos
Fibonacci
Clculo del coeficiente binomial

Ejercicios: Programacin dinmica de Fibonacci

y Coeficientes Binomiales

Introduccin
La tcnica divide y vencers seala que es posible dividir

un problema en subproblemas y combinar las soluciones


para resolver el problema original.
En

ocasiones resolver subproblemas nos lleva a


considerar subproblemas idnticos.

Si

aprovechamos la duplicacin, resolviendo cada


problema una sola vez, guardando la solucin para su
uso posterior entonces tendremos un algoritmo ms
eficiente.

La idea de la programacin dinmica es evitar repeticin

de clculos.
La

base de la programacin
razonamiento inductivo:

dinmica

es

el

Como resolver un problema combinando soluciones

para problemas ms pequeos?


Se resuelven primero los subproblemas ms pequeos

y por tanto ms simples. Combinando las soluciones


se
obtienen
las
soluciones
de
ejemplares
sucesivamente ms grandes hasta llegar al ejemplar
original.

Programacin dinmica
La programacin dinmica es un mtodo para reducir

el tiempo de ejecucin de un algoritmo mediante la


utilizacin
de
subproblemas
superpuestos
y
subestructuras ptimas.
Una subestructura ptima significa que se pueden usar

soluciones ptimas de subproblemas para encontrar


la solucin ptima del problema en su conjunto.
Un problema tiene subproblemas superpuestos si se

usa un mismo subproblema para resolver diferentes


problemas mayores.

Los algoritmos divide y vencers estn dentro de los

mtodos descendentes.
Empezar con el problema original y descomponerlo en
pasos sucesivos en problemas de menor tamao.
La programacin dinmica por el contrario, es un

mtodo ascendente:
Resolver primero los problemas pequeos (guardando
las soluciones) y despus combinarlas para resolver
problemas ms grandes.
La programacin dinmica hace uso de:
Subproblemas superpuestos
Subestructuras ptimas
Memoizacion

En general, se pueden resolver problemas con

subestructuras ptimas siguiendo estos tres


pasos:
1. Dividir

el problema en subproblemas ms
pequeos.
2. Resolver estos problemas de manera ptima
usando este proceso de tres pasos recursivamente.
3. Usar estas soluciones ptimas para construir una
solucin ptima al problema original.
Los

subproblemas se resuelven a su vez


dividindolos en subproblemas ms pequeos
hasta que se alcance el caso fcil, donde la
solucin al problema es trivial.

Los subproblemas superpuestos provocan resolver

varias veces el mismo problema, ya que la solucin de


un subproblema requiere calcular soluciones que otro
subproblema tambin tenga que calcular.
Perder tiempo calculando varias veces la solucin al

mismo subproblema se puede evitar guardando las


soluciones que ya hemos calculado. Entonces, si
necesitamos resolver el mismo problema ms tarde,
podemos obtener la solucin de la lista de soluciones
calculadas y reutilizarla. Este acercamiento al problema
se
llama
memoizacion
(no
confundir
con
memorizacin; en ingls es llamado memoization).
En programacin dinmica comnmente se utilizan

tablas de resultados conocidos que se va generando a


medida que se resuelven los subcasos.

Originalmente, el trmino de programacin dinmica se

refera a la resolucin de ciertos problemas y


operaciones fuera del mbito de la Ingeniera
Informtica, al igual que haca la programacin lineal.
Aquel contexto no tiene relacin con la programacin en
absoluto; el nombre es una coincidencia. El trmino
tambin lo us en los aos 40 Richard Bellman, un
matemtico norteamericano, para describir el proceso de
resolucin de problemas donde hace falta calcular la
mejor solucin consecutivamente.
Algunos lenguajes de programacin funcionales, sobre

todo
Haskell,
pueden
usar
la
memoizacion
automticamente sobre funciones con un conjunto
concreto de argumentos, para acelerar su proceso de
evaluacin. Esto slo es posible en funciones que no
tengan efectos secundarios.

Donde tiene mayor aplicacin la Programacin

Dinmica es en la resolucin de problemas de


optimizacin. En este tipo de problemas se pueden
presentar distintas soluciones, cada una con un
valor, y lo que se desea es encontrar la solucin de
valor ptimo (mximo o mnimo).
La solucin de problemas mediante esta tcnica se

basa en el llamado principio de ptimo enunciado


por Bellman en 1957 y que dice:

En una secuencia de decisiones ptima toda


subsecuencia ha de ser tambin ptima.

Enfoques de la programacin dinmica


Top-down: El problema se divide en subproblemas, y

estos se resuelven recordando las soluciones por si


fueran necesarias nuevamente. Es una combinacin de
memoizacin y recursin.
Bottom-up:

Todos los problemas que puedan ser


necesarios se resuelven de antemano y despus se usan
para resolver las soluciones a problemas mayores. Este
enfoque es ligeramente mejor en consumo de espacio y
llamadas a funciones, pero a veces resulta poco intuitivo
encontrar todos los subproblemas necesarios para
resolver un problema dado.

Principio de optimalidad
Cuando hablamos de optimizar nos referimos a buscar

alguna de las mejores soluciones de entre muchas


alternativas posibles. Dicho proceso de optimizacin
puede ser visto como una secuencia de decisiones que
nos proporcionan la solucin correcta.
En este caso sigue siendo posible el ir tomando

decisiones elementales, en la confianza de que la


combinacin de ellas seguir siendo ptima, pero ser
entonces necesario explorar muchas secuencias de
decisiones para dar con la correcta, siendo aqu donde
interviene la programacin dinmica.

En una secuencia de decisiones ptima toda


subsecuencia ha de ser tambin ptima
Contemplar un problema como una secuencia de

decisiones equivale a dividirlo en problemas ms


pequeos y por lo tanto ms fciles de resolver
como hacemos en Divide y Vencers. La
programacin dinmica se aplica cuando la
subdivisin de un problema conduce a:
Una enorme cantidad de problemas.
Problemas cuyas soluciones parciales se solapan.
Grupos de problemas de muy distinta complejidad.

Diseo de un algoritmo de programacin


dinmica
Para que un problema pueda ser abordado por esta

tcnica ha de cumplir dos condiciones:


La solucin al problema ha de ser alcanzada a travs de

una secuencia de decisiones, una en cada etapa.


Dicha secuencia de decisiones ha de cumplir el principio

de optimalidad.

El diseo de un algoritmo de Programacin Dinmica

consta de los siguientes pasos:


1. Planteamiento de la solucin como una sucesin
de decisiones y verificacin de que sta cumple el
principio de ptimo.
2.

Definicin recursiva de la solucin.

3.

Clculo del valor de la solucin ptima mediante


una estructura de datos en donde se almacenan
soluciones a problemas parciales para reutilizar los
clculos.

4.

Construccin de la solucin ptima haciendo uso


de la informacin contenida en la estructura de
datos.

Fibonacci
( )

Si se llama a fib(5), se produce un rbol de llamadas que contendr

funciones con los mismos parmetros varias veces:


1.
2.
3.

4.
5.

fib(5)
fib(4) + fib(3)
(fib(3) + fib(2)) + (fib(2) + fib(1))
((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
(((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))

En particular, fib(2) se calcula dos veces. En ejemplos mayores, se

recalculan muchos otros valores de fib, o subproblemas.


Para evitar este inconveniente, se puede resolver el problema mediante

programacin dinmica, y en particular, utilizando el enfoque de


memoizacin (guardar los valores que ya han sido calculados para
utilizarlos posteriormente). As, rellenaramos una tabla con los
resultados de los distintos subproblemas, para reutilizarlos cuando haga
falta en lugar de volver a calcularlos. La tabla resultante sera una tabla
unidimensional con los resultados desde 0 hasta n.

Fibonacci utilizando (Programacin


dinmica - Buttom-up)
int fibonacci(int n)
{
int i;
if (n<2)
{
return n;
}
else
{
tabla[0] = 0;
tabla[1] = 1;
for(i = 2; i < n; i++)
tabla[i] = tabla[i-1] + tabla[i-2];
}
return tabla[n-1];
}

()

Fibonacci utilizando (Programacin


dinmica -Top-down)
int tabla[n]; // tabla {-1,-1,,-1}

int fibonacci(int n)
{
if (n<2)
return n;
if(tabla[n-1] == -1)
tabla[n-1] = fibonacci(n-1);
if(tabla[n-2] == -1)
tabla[n-2] = fibonacci(n-2);
tabla[n] = tabla[n-1] + tabla[n-2];
return tabla[n];
}

()

Clculo del coeficiente binomial


Los coeficientes binomiales o nmeros combinatorios son

una serie de nmeros estudiados en combinatoria que indican


el nmero de formas en que se pueden extraer subconjuntos
a partir de un conjunto dado. Sin embargo, dependiendo del
enfoque que tenga la exposicin, se suelen usar otras
definiciones equivalentes.
A,B
P.g. Se tiene un conjunto con 6
objetos diferentes {A,B,C,D,E,F}, de
los cuales se desea escoger 2 (sin
importar el orden de eleccin).
Cuntas
formas
de
eleccin
existen?

A,C

A,D

A,E

A,F

B,C

B,D

B,E

B,F

C,D

C,E

C,F

D,E

D,F
E,F

El nmero de formas de escoger k elementos a partir de

un conjunto de n, puede denotarse de varias formas:


(, ),

(6,2) = 15
Los nmeros C(n,k) se conocen como coeficientes

binomiales, pero es frecuente referirse a ellos como


combinaciones de n en k, o simplemente n en k.

El coeficiente binomial es el nmero de


subconjuntos de k elementos escogidos de un
conjunto con n elementos
El coeficiente binomial

est dado por la frmula


!
! !

Forma recursiva del coeficiente binomial

= 0 =

1
1
+
0 < <
1

Si se desea calcular C(5,3), Cules son los casos que

se repiten?
funcion C(n,k)
{
Si k = 0 o k = n entonces
devolver 1
sino si 0 < k< n
devolver C(n-1,k-1) + C(n-1,k)
sino
devolver 0
}

El algoritmo recursivo que los calcula resulta ser de

complejidad exponencial
por la repeticin de los
clculos que realiza. No obstante, es posible disear un
algoritmo con un tiempo de ejecucin de orden O(nk)
basado en la idea del Tringulo de Pascal. Para ello es
necesario la creacin de una tabla bidimensional en la
que ir almacenando los valores intermedios que se
utilizan posteriormente.

Se ira construyendo la tabla por filas de arriba hacia

abajo y de izquierda a derecha mediante el siguiente


algoritmo de complejidad polinmica (Bottom-up).
int coef_bino(int n, int k)
{
int i, j;
for(i = 0; i <= n; i++)
tabla[i][0] = 1;
for(i = 1; i<= n; i++)
tabla[i][1] = i;
for(i = 2; i<= k; i++)
tabla[i][i] = 1;

for(i = 3; i <= n; i++)


for(j = 2; j <= i-1; j++)
if(j <= k)
tabla[i][j] = tabla[i-1][j-1] + tabla[i-1][j];
return tabla[n][k];
}

Resultado Triangulo de Pascal

Ejercicios: Programacin dinmica de Fibonacci y


Coeficientes Binomiales
Entender e implementar los algoritmos basados en

programacin dinmica de Fibonacci (top down y botton


up) y de coeficientes binomiales.
Describir de manera detallada los algoritmos y su

implementacin.
*Enviar con su rbrica correspondiente.

Vous aimerez peut-être aussi