Вы находитесь на странице: 1из 45

ALGORITMICA III

Programacin Dinmica
Docente: Carlos A.Ruiz De La Cruz Melo
Correo: zorroculto69@hotmail.com
Existe una serie de problemas cuyas
soluciones pueden ser expresadas
recursivamente en trminos matemticos,
y posiblemente la manera ms natural de
resolverlos es mediante un algoritmo
recursivo.

Sin embargo, el tiempo de ejecucin de la
solucin recursiva, normalmente de orden
exponencial y por tanto impracticable,
puede mejorarse substancialmente
mediante la Programacin Dinmica.
INTRODUCCION
En el diseo Divide y Vencers nosotros
veamos cmo para resolver un problema lo
dividamos en subproblemas independientes,
los cuales se resolvan de manera recursiva
para combinar finalmente las soluciones y as
resolver el problema original.

El inconveniente se presenta cuando los
subproblemas obtenidos no son
independientes sino que existe
solapamiento entre ellos; entonces es
cuando una solucin recursiva no resulta
eficiente por la repeticin de clculos
que conlleva.
INCONVENIENTES EN
DIVIDE Y VENCERS
SIMILITUD:
Descomposicin del problema.
Se obtiene aplicando un razonamiento
inductivo.

DIFERENCIA:
Divide y vencers: aplicar directamente
la frmula recursiva.
Programacin dinmica: resolver los
problemas ms pequeos, guardando
los resultados en una tabla (programa
iterativo).

MTODOS
Divide y vencers utiliza el mtodo
descendente
La programacin dinmica usa el
mtodo ascendente

DIVIDE Y VENCERAS VS
PROGRAMACION DINAMICA
La Programacin Dinmica nos puede
ofrecer una solucin aceptable a los
inconvenientes del Divide y Vencers.
La eficiencia de esta tcnica consiste
en resolver los subproblemas una sola
vez, guardando sus soluciones en una
tabla para su futura utilizacin.

La Programacin Dinmica no slo
tiene sentido aplicarla por razones de
eficiencia, sino porque adems
presenta un mtodo capaz de resolver
de manera eficiente problemas cuya
solucin ha sido abordada por otras
tcnicas y ha fracasado.
RAZON DELA PROGRAMACION
DINAMICA (D.N.)
DEFINICION:
En informtica, la programacin
dinmica es un mtodo para
reducir el tiempo de ejecucin de
un algoritmo mediante la
utilizacin de subproblemas
superpuestos y subestructuras
ptimas.
Para que un problema pueda ser abordado
por esta tcnica ha de cumplir dos
condiciones:

1. La solucin al problema ha de
ser alcanzada a travs de una
secuencia de decisiones, una
en cada etapa.

2. Dicha secuencia de decisiones
ha de cumplir el principio de
ptimo.
CONDICIONES
DE LA P.D.
La solucin de problemas mediante esta
tcnica se basa en el llamado principio
de ptimo enunciado por Bellman en 1957
y que dice:

PRINCIPIO DE PTIMO
En una secuencia de decisiones
ptima toda subsecuencia ha de ser
tambin ptima.
Hemos de observar que aunque este principio parece evidente no siempre es
aplicable y por tanto es necesario verificar que se cumple para el problema en
cuestin. Un ejemplo claro para el que no se verifica este principio aparece al
tratar de encontrar el camino de coste mximo entre dos vrtices de un grafo
ponderad
En grandes lneas, el diseo de un
algoritmo de Programacin Dinmica
consta de los siguientes pasos:
DISEO DE ALGORITMOS DE P.D.
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 tabla 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 tabla anterior.
Una subestructura ptima significa que se
pueden usar soluciones ptimas de
subproblemas para encontrar la solucin
ptima del problema en su conjunto. En
general, se pueden resolver problemas con
subestructuras ptimas siguiendo estos tres
pasos:
SUBESTRUCTURA PTIMA
1. Dividir el problema (proceso
inductivo)

2. Resolver estos subproblemas

3. Recomponer la solucin final
En resumen, la programacin hace uso de:

Subproblemas superpuestos

Decir que un problema tiene
subproblemas superpuestos es decir
que se usa un mismo subproblema
para resolver diferentes problemas
mayores.

Subestructuras ptimas

soluciones ptimas de subproblemas
para encontrar la solucin ptima del
problema en su conjunto.

Memorizacin

Se guarda las soluciones que ya
se han calculado

PROGRAMACION DINAMICA
ENFOQUES DE LA P.D.
Top-down:

El problema se divide en subproblemas,
y estos se resuelven recordando las
soluciones por si fueran necesarias
nuevamente. Es una combinacin de
memorizacin 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.

> +
=
=
1 ) 2 ( ) 1 (
1 , 0 1
) (
n si n Fib n Fib
n si
n Fib
CALCULO DE LOS NUMEROS
FIBONACCI
La sucesin Fibonacci podemos
expresarla recursivamente en trminos
matemticos de la siguiente manera
funcion Fib(n):entero
si n 1 entonces
retornar 1
sino
retornar Fib(n-1) + Fib(n-2)
finsi
finFib
Por tanto, la forma ms
natural de calcular los
trminos de esa sucesin
es mediante un programa
recursivo:
Muchos clculos estn repetidos. No se
conservan los resultados previos y se
tienen que volver a calcular
ARBOL FIBONACCI
Fib(4)
Fib(3) + Fib(2)
Fib(2) + Fib(1)
Fib(1) + Fib(0)
Fib(1) + Fib(0) Fib(0) + Fib(-1) Fib(0) + Fib(-1)
OPERACIONF REPITENCIAS
Fib(2) 2
Fib(1) 3
Fib(0) 4
Fib(-1) 2
Podemos resolver el problema
mediante programacin
dinmica, y en particular,
utilizando el enfoque de
memorizacin (guardar los
valores que ya han sido
calculados para utilizarlos
posteriormente). Llenamos una
tabla con los resultados de los
distintos subproblemas.
(BOTTOM-UP)
Procedimiento Fibo (n)
arreglo: tabla
i : natural
si n 1 entonces
retornar 1
sino
tabla[0] 0
tabla[1] 1
para i 2 hasta n hacer
tabla[i] tabla[i-1] + tabla[i-2]
finpara
retornar tabla[n]
finsi
finfibo
SOLUCION FIBONACCI ITERATIVO
COEFICIENTE
BINOMIAL
Los coeficientes binomiales, nmeros
combinatorios o combinaciones son
nmeros estudiados en combinatoria que
corresponden al nmero de formas en que
se pueden extraer subconjuntos a partir de
un conjunto dado.
El nmero de formas de escoger k elementos a
partir de un conjunto de n, puede denotarse de
varias formas:




~
~
~
COEFICIENTE
BINOMIAL
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). Existen 15 formas de efectuar tal
eleccin:
{ (A,B), (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) }
6

2
15
TRIANGULO DE PASCAL
Se tiene una cuadrcula
rectangular en la cual se escribe
el nmero 1 en las casillas del
borde superior y el borde
izquierdo:
1 1 1 1
1
1
1

En cada casilla se escribe la suma de
los valores de las dos casillas
contiguas situadas a su izquierda y
en la parte superior:
1 1 1 1
1 2 3 4
1 3 6 10
1 4 10 20

TRIANGULO DE PASCAL
Es comn, sin embargo,
presentar el arreglo en forma
triangular, con los bordes
inclinados, tal como se ilustra en
la figura.
1 1 1 1
1 2 3 4
1 3 6 10
1 4 10 20

TRIANGULO DE PASCAL
Se observa que para cualquier entero n, se
cumple que slo hay una forma de escoger
cero o todos los elementos de un conjunto
dado.
n
0
= 1 =
n
n
1 1 1 1
1
1
1

C(0,0) C(1,1) C(2,2) C(3,3)
C(1,0)
C(2,0)
C(3,0)
TRIANGULO DE PASCAL
Se observa tambin que las
dems casillas del arreglo son
coeficientes binomiales:
1 1 1 1
1 2 3 4
1 3 6 10
1 4 10 20

C(0,0) C(1,1) C(2,2) C(3,3)
C(1,0) C(2,1) C(3,2) C(4,3)

C(2,0) C(3,1) C(4,2) C(5,3)

C(3,0) C(4,1) C(5,2) C(6,3)


3
)! 2 3 ( ! 2
! 3
=

1
0
, 0
1
1
1
=
|
|
.
|

\
|
=
|
|
.
|

\
|
< <
|
|
.
|

\
|

+
|
|
.
|

\
|

=
|
|
.
|

\
|
n
n n
n k si
k
n
k
n
k
n
COEFICIENTES BINOMIALES
La afirmacin de que las entradas del triangulo
de Pascal son precisamente los coeficientes
binomiales, se basa en la siguiente identidad,
conocida ahora como identidad de Pascal o
teorema de pascal.
En la resolucin de un problema, una vez encontrada la
expresin recursiva que define su solucin, muchas veces
la dificultad estriba en la creacin del vector o la tabla que
ha de conservar los resultados parciales.

As en este segundo ejemplo, aunque tambin sencillo,
observamos que vamos a necesitar una tabla
bidimensional algo ms compleja. Se trata del clculo de
los coeficientes binomiales, definidos como:
COEFICIENTES BINOMIALES

COEFICIENTES BINOMIALES MAS
EFICIENTE
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
#include<iostream.h>
#include<conio.h>
int factorial(int n){
if(n<2) return 1;
else return n * factorial(n-1);
}

int combinacion(int n, int r){
if(r==1)return n;
else{
if(n==r) return 1;
else return factorial(n)/(factorial(r)*factorial(n - r));
}
}

int main(){
for(int i=0; i<=6; i++) {
for(int ii=0; ii<=i; ii++)
cout << combinacion(i, ii) << " ";
cout << endl;
}
getch();
return 0;
}
PROGRAMA 1: TRIANGULO DE
PASCAL
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
PROGRAMA 2:
TRIANGULO DE
PASCAL
#include<conio.h>
#include<stdio.h>
main(){
printf("\t\t triangulo de pascal\n");
int trian[100][100]={0}, h, n, i, j;
do{
printf("Ingrese el Alto del Triangulo[1-25]= ");
scanf("%d",&h);
}while(h<1 || h>100);
n=(2*h)-1;
trian[0][h-1]=1;
for (i=1; i<=h; i++){
for (j=h+1-i; j <= i-h+n ; j++){
trian[i][j]= trian[i-1][j-1] + trian[i-1][j+1];
}
}
for (i=1;i<=h;i++){
for (j=1;j<=n;j++){
if (trian[i][j]!=0){
printf("%2d",trian[i][j]);
}
else{
printf(" ");
}
}
printf("\n");
}
getch();
}
triangulo de pascal
Ingrese el Alto del Triangulo[1-25]= 7
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
Sea G = {N, A} un grafo dirigido, N
conjunto de nodos y A conjunto de
aristas.

Toda arista tiene una longitud no
negativa.

Se desea calcular la longitud del
camino ms corto entre cada par de
nodos.

Por ejemplo:

ALGORITMO DE CAMINOS MNIMOS
Para k desde 1 hasta n hacer
Para i desde 1 hasta n hacer
Para j desde 1 hasta n hacer
D[i, j] minimo((D[i, k]+ D[k, j]) , D[i, j])
Fin Para
Fin Para
Fin Para
Para calcular el menor de los caminos
mnimos entre dos vrtices
cualesquiera del grafo podemos
aplicar el algoritmo de Floyd.

ALGORITMO DE CAMINOS MNIMOS
ALGORITMO DE CAMINOS MNIMOS
1 2 3 4
1 0 5
2 50 0 15 5
3 30 0 15
4 15 5 0
L = D
0
=
Dada la matriz L de adyacencia del
grafo G, se calcula una matriz D con la
longitud del camino mnimo que une
cada par de vrtices.
Matriz de
adyacencia
Nos planteamos si tal algoritmo puede ser
considerado o no de Programacin Dinmica,
es decir, si reune las caractersticas
esenciales de ese tipo de algoritmos.

Este algoritmo puede ser considerado de
Programacin Dinmica ya que es aplicable el
principio de ptimo, que puede enunciarse
para este problema de la siguiente forma:
si en el camino mnimo de vi a v
j
, v
k
es un vrtice
intermedio, los caminos de v
i
a v
k
y de v
k
a v
j
han
de ser a su vez caminos mnimos
ALGORITMO DE CAMINOS MNIMOS
ALGORITMO DE CAMINOS MNIMOS
)} , ( ), , ( { ) , (
1 1
1
j k D k i D Min j i D
k k
k
k
>
=
Siguiendo el esquema de la
Programacin Dinmica, utiliza una
matriz para evitar la repeticin de los
clculos.

Con ello consigue que su complejidad
temporal sea de orden O(n3) debido
al triple bucle anidado en cuyo interior
hay tan slo operaciones constantes
Por lo tanto, puede plantearse la relacin en
recurrencia que resuelve el problema como:
Para k=1
1 2 3 4
1 0 5
2 50 0 15 5
3 30 35 0 15
4 15 20 5 0
Para k=2
1 2 3 4
1 0 5 20 10
2 50 0 15 5
3 30 35 0 15
4 15 20 5 0
D[2,1]=min(D[2,1]+D[1,1] , D[2,1])
50 =min( 50+ 0 , 50 )
D[2,1]=min(D[2,2]+D[2,1] , D[2,1])
50 =min( 0+ 50 , 50 )
ALGORITMO DE CAMINOS MNIMOS
)} , ( ), , ( { ) , (
1 1
1
j k D k i D Min j i D
k k
k
k
>
=
1 2 3 4
1 0 5
2 50 0 15 5
3 30 0 15
4 15 5 0
Para k=3

Para k=4

1 2 3 4
1 0 5 20 10
2 45 0 15 5
3 30 35 0 15
4 15 20 5 0
1 2 3 4
1 0 5 15 10
2 20 0 10 5
3 30 35 0 15
4 15 20 5 0
D[2,1]=min(D[2,3]+D[3,1] , D[2,1])
45 =min( 50 + 30 , 50 )
D[2,1]=min(D[2,4]+D[4,1] , D[2,1])
45 =min( 5 + 15 , 45 )
ALGORITMO DE CAMINOS MNIMOS
)} , ( ), , ( { ) , (
1 1
1
j k D k i D Min j i D
k k
k
k
>
=
DEVOLUCION DE MONEDAS
Para el problema de las monedas con
programacin dinmica se necesita crear
un algoritmo que permita a una mquina
expendedora devolver el cambio mediante el
menor nmero de monedas posible.

El denominado problema de la moneda"
es el siguiente: dados diferentes tipos de
monedas, cada uno con un valor diferente, y
una cantidad C, cul es el menor nmero de
monedas necesarias para devolver el cambio
C?

1. Coge una moneda con el valor V ms
grande tal que V <= C
2. Repite desde 1 con el valor C - V hasta
que C = 0

DEVOLUCION DE MONEDAS
Estrategia bsica para resolver
el problema
Sin embargo, esta estrategia no funciona para valores
aleatorios de las monedas. Por ejemplo, si las monedas tienen
valores 1, 4 y 6, el nmero mnimo de monedas para hacer un
cambio de 8 es 2 monedas de 4 (cogiendo una moneda de 6
necesitamos como mnimo 3 monedas en total).
DEVOLUCION DE MONEDAS
Supongamos que se tienen monedas
de valor 1, 4 y 6 y que se debe devolver
una cantidad correspondiente al valor
8. Siguiendo el mtodo de la
programacin dinmica, se rellenar
una tabla con las filas correspondientes
a cada valor para las monedas y las
columnas con valores desde el 1 hasta
el 8.

Cada posicin (i, j) de la tabla nos
indica el nmero mnimo de monedas
requeridas para devolver la cantidad j
con monedas con valor menor o igual
al de i:
1 2 3 4 5 6 7 8
m1=1 1 2 3 4 5 6 7 8
m2=4 1 2 3 1 2 3 4 2
m3=6 1 2 3 1 2 1 2 2
para la posicin i = 2 y j = 7, se requiere una
moneda tipo 2 con valor 4 y tres monedas de tipo 1
con valor uno, por lo tanto en la tabla el nmero de
monedas en la posicin (2,7) ser 1 + 3 = 4.
DEVOLUCION DE MONEDAS
Ejemplo
1 2 3 4 5 6 7 8
m1=1 1 2 3 4 5 6 7 8
m2=4 1 2 3 1 2 3 4 2
m3=6 1 2 3 1 2 1 2 2
Cada posicin (i, j) de la tabla nos indica el
nmero mnimo de monedas requeridas
para devolver la cantidad j con monedas
con valor menor o igual al de i:
1. Para cada casilla de la tabla hacer:
2. Si el valor de la moneda actual es mayor
que la cantidad, se paga con el resto de
monedas, es decir, se toma el resultado de
la casilla superior.
3. Si el valor de la moneda actual es menor o
igual que la cantidad, se toma el mnimo
entre:

1. Pagar con el resto de monedas,
tomando el resultado de la casilla
superior.
2. Pagar con una moneda del tipo actual y
el resto con el resultado que se hubiera
obtenido al pagar la cantidad actual a
la que se le ha restado el valor de la
moneda actual.

4. Tomar como resultado el valor de la ltima
celda.
DEVOLUCION DE MONEDAS
Algoritmo
1 2 3 4 5 6 7 8
m1=1 1 2 3 4 5 6 7 8
m2=4 1 2 3 1 2 3 4 2
m3=6 1 2 3 1 2 1 2 2
#include <stdio.h>
#include <stdlib.h>
#define MONEDAS 8
int monedas[] = {200,100,50,20,10,5,2,1};
int solucion[MONEDAS];
int main (){
int i, devolucion;
printf("devolucion: ");
scanf ("%d",&devolucion);
//inicializacion de vector solucion
for (i = 0; i < MONEDAS; i++)
solucion[i] =0; //-- //-- bucle voraz
for (i = 0; i < MONEDAS; i++)
while (devolucion >= monedas[i]){
solucion[i]++;
devolucion-= monedas[i];
}
//-- fin del bucle voraz
if (devolucion) // !0
printf ("No hay monedas para devolver\n");
else //mostramos la solucion
for (i = 0; i < MONEDAS; i++)
if (solucion[i])
printf ("%d modenas de %d\n", solucion[i], monedas[i]);
system ("pause");
return 0;
}
SOLUCION VORAZ
SALIDA DEL PROGRAMA

devolucion: 67
1 modenas de 50
1 modenas de 10
1 modenas de 5
1 modenas de 2
Presione una tecla para continuar . . .
DEVOLUCION DE MONEDAS
En general, para resolver el problema de
la moneda tenemos que probar todas las
posibles combinaciones de coger
monedas.

Para la cantidad C, las posibilidades son:
coger una moneda del primer tipo, coger
una moneda del segundo tipo, etc. En
cada caso se genera un subproblema del
mismo tipo por resolver. Por ejemplo, si
cogemos una moneda de valor 1,
recursivamente tenemos que encontrar la
mejor manera de devolver el cambio C-1,
y sumarle 1 para obtener una posible
solucin para C.

La solucin para C es la mejor entre
todas estas posibles maneras de coger la
primera moneda.
Si denominamos A(C) el subproblema para
la cantidad C, una definicin resursiva para
el problema es:

donde k es el nmero total de monedas y
m_i es el valor de la moneda i. Ahora
podemos escribir una solucin basada en
la programacin dinmica:
A(0) = 0 (si la cantidad es 0 no necesitamos ninguna moneda)
A(C) = min(1 + A(C-m_1), 1 + A(C-m_2), ..., 1 + A(C-m_k))
DEVOLUCION DE MONEDAS
SOLUCION DINAMICA
int main() {
int M[3] = {1, 4, 9};
int res[101];
res[0] = 0;
for (int c = 1; c <= 100; ++c) {
res[c] = c;
for (int i = 0; i < 3; ++i)
if (M[i] <= c && 1 + res[c - M[i]] < res[c])
res[c] = 1 + res[c - M[i]];
}

cout << res[1] << endl;
cout << res[12] << endl;
cout << res[20] << endl;
cout << res[22] << endl;
getch();
}
Despus del bucle el array res
contendr el resultado para cada
C en el rango [0, 100].
SALIDA DEL PROGRAMA

1
3
4
3
1
4
9
MONEDAS
SOLUCION DINAMICA
1
4
9
MONEDAS
SALIDA DEL PROGRAMA

1
3
4
3
La cantidad C=1 se paga con 1 moneda
La cantidad C=12 se paga con 3 monedas
La cantidad C=20 se paga con 4 monedas
La cantidad C=22 se paga con 3 monedas
2 de 9
1 de 4
EN RESUMEN
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, tcnica similar a la de
programacin dinmica. 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
CONCLUSIONES
Una funcin recursiva gasta un poco de
memoria y tiempo en cada llamada
recursiva. Por esta razn, la programacin
dinmica prescinde de la recursividad y
resuelve el problema exclusivamente con la
iteracin.

Вам также может понравиться