Docsity
Docsity

Prepara tus exámenes
Prepara tus exámenes

Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity


Consigue puntos base para descargar
Consigue puntos base para descargar

Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium


Orientación Universidad
Orientación Universidad


Programación Dinámica: Métodos, Ejemplos y Análisis, Apuntes de Ciencias

La programación dinámica, un método utilizado en problemas de optimización donde una solución está formada por una serie de decisiones. Se trata de un enfoque ascendente que resuelve primero los problemas pequeños y luego combina las soluciones para resolver los problemas más grandes. Se incluyen ejemplos de aplicación como el problema del cambio de monedas y la mochila 0/1, así como el análisis de tiempos de ejecución.

Tipo: Apuntes

2017/2018

Subido el 07/10/2021

jorge-esquerre
jorge-esquerre 🇲🇽

7 documentos

1 / 16

Toggle sidebar

Esta página no es visible en la vista previa

¡No te pierdas las partes importantes!

bg1
Programación dinámica
1. Método general.
2. Análisis de tiempos de ejecución.
3. Ejemplos de aplicación.
3.1. Problema del cambio de monedas.
3.2. Problema de la mochila 0/1.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff

Vista previa parcial del texto

¡Descarga Programación Dinámica: Métodos, Ejemplos y Análisis y más Apuntes en PDF de Ciencias solo en Docsity!

Programación dinámica

1. Método general.

2. Análisis de tiempos de ejecución.

3. Ejemplos de aplicación.

3.1. Problema del cambio de monedas.

3.2. Problema de la mochila 0/1.

Método general

  • (^) La programación dinámica se suele utilizar en problemas de

optimización , donde una solución está formada por una serie de

decisiones.

  • (^) Igual que la técnica divide y vencerás , resuelve el problema

original combinando las soluciones para subproblemas más

pequeños.

  • (^) Sin embargo, la programación dinámica no utiliza recursividad,

sino que almacena los resultados de los subproblemas en una

tabla , calculando primero las soluciones para los problemas

pequeños.

  • (^) Con esto se pretende evitar la repetición de cálculos para

problemas más pequeños.

Método general

  • (^) Los algoritmos divide y vencerás están dentro de los métodos

descendentes.

  • (^) Empezar con el problema original y descomponer en pasos

sucesivos en problemas de menor tamaño.

  • (^) Partiendo del problema grande, descendemos hacia problemas

más sencillos.

  • (^) La programación dinámica , por el contrario, es un método

ascendente :

  • (^) Resolvemos primero los problemas pequeños (guardando las

soluciones en una tabla) y después vamos combinando para

resolver los problemas más grandes.

Método general

  • (^) La programación dinámica se basa en el Principio de Optimalidad

de Bellman : cualquier subsecuencia de una secuencia óptima

debe ser, a su vez, una secuencia óptima.

  • (^) Para cada problema deberíamos comprobar si es aplicable el

principio de optimalidad.

  • (^) Ejemplo.

2 B 9

A D

3 C 7

Camino óptimo de A a D: A-C-D, de longitud 10

Camino óptimo de A al siguiente nivel: A-B, de longitud 2, y

después B-D de longitud 9. Total: A-B-D, de longitud 11

¿Cumple el Principio de Optimalidad?

Análisis de tiempos de ejecución

  • (^) El tiempo de ejecución depende de las características concretas

del problema a resolver.

  • (^) En general, será de la forma:

Tamaño de la tabla*Tiempo de rellenar cada elemento de la

tabla.

  • (^) Un aspecto importante de los algoritmos de programación

dinámica es que necesitan una tabla para almacenar los

resultados parciales, que puede ocupar mucha memoria.

  • (^) Además, algunos de estos cálculos pueden ser innecesarios.
  • (^) Problema: Dado un conjunto de n tipos de monedas, cada una con valor ci , y dada una cantidad P , encontrar el número mínimo de monedas que tenemos que usar para obtener esa cantidad.
  • (^) El algoritmo voraz es muy eficiente, pero sólo funciona en un número limitado de casos.
  • (^) Utilizando programación dinámica:
    • (^) Definimos el problema en función de problemas más pequeños.
    • (^) Determinar los valores de los casos base.
    • (^) Definimos las tablas necesarias para almacenar los resultados

de los subproblemas.

  • (^) Establecemos una forma de rellenar las tablas y de obtener el

resultado.

Problema del cambio de monedas

Problema del cambio de monedas

Definición de las tablas utilizadas:

  • (^) Necesitamos almacenar los resultados de todos los subproblemas.
  • (^) El problema a resolver será: Cambio (n, P).
  • (^) Por lo tanto, necesitamos una tabla de nxP, de enteros, que llamaremos D , siendo D[i, j ]= Cambio(i, j).
  • (^) Ejemplo. n= 3, P= 8, c= (1, 4, 6) Forma de rellenar las tablas:
  • (^) De arriba hacia abajo y de izquierda a derecha, aplicar la ecuación de recurrencia: D[i, j] = mink=0,1,...,Q/ci {D(i-1, Q-k* ci)+k} D Cantidad a devolver Monedas 0 1 2 3 4 5 6 7 8 C 1 = 1 C 2 = 4 C 3 = 6

Problema del cambio de monedas

  • (^) Algoritmo. Devolver-cambio (P: int; C: array [1..n] of int; var D: array [1..n, 0..P] of int); para i = 1,2,...,n D[i, 0] = 0 para i = 1,2,...,n para j = 1,2,...,P {Tener en cuenta si el valor } D[i, j] = mink=0,1,...,Q/ci {D(i-1, Q-k* ci)+k} { cae fuera de la tabla}
  • (^) Ejemplo. n= 3, P= 8, c= (1, 4, 6)
  • (^) ¿Cuál es el tiempo de ejecución del algoritmo?
  • (^) ¿Cómo es en comparación con el algoritmo voraz?
  • (^) D[n, P]: número mínimo de monedas que hay que usar para devolver la cantidad P. 0 1 2 3 4 5 6 7 8 C 1 = 1 0 1 2 3 4 5 6 7 8 C 2 = 4 0 1 2 3 1 2 3 4 2 C 3 = 6 (^) 0 1 2 3 1 2 1 2 2

Problema de la mochila 0/

  • (^) Igual que en el tema anterior, pero los objetos no se pueden fragmentar en trozos más pequeños.
  • Problema:^ Tenemos^ n^ objetos, cada uno con un peso ( wi ) y un beneficio ( vi ), y una mochila en la que podemos meter objetos, con una capacidad de peso máximo M. El objetivo es maximizar el beneficio de los objetos transportados, donde cada objeto se puede coger entero (xi=1) o nada (xi=0). Definición de la ecuación recurrente:

• Sea Mochila (i, m) el problema de la mochila,

considerando sólo los i primeros objetos (de los n

originales) con una capacidad de peso m.

Supondremos que devuelve el valor de beneficio

total:  x

a

·v

a a=1..i

• Podemos definir el problema de forma recurrente,

en función de que se use o no el objeto i.

Problema de la mochila 0/

Definición de la ecuación recurrente:

  • (^) Si no se usa el objeto i : Mochila (i, m) = Mochila (i - 1, m)
  • Si se usa: Mochila (i, m) = vi + Mochila (i - 1, m - wi)
  • (^) Valor óptimo: Mochila (i, m) = max (Mochila (i-1, m), vi + Mochila (i-1, m - wi)) Casos base:
  • (^) Si (i<0) o (m<0) entonces no hay solución: Mochila (i, m) = -
  • (^) En otro caso, si (i=0) ó (m=0) la solución es no incluir ningún objeto: Mochila (i, m) = 0 Definición de las tablas:
  • (^) La solución del problema original será Mochila (n, M).
  • (^) Por lo tanto necesitamos una tabla: V : array [0..n, 0..M] of integer.
  • (^) V[i, j] = Beneficio máximo usando los i primeros objetos y peso j.

Problema de la mochila 0/

  • (^) Se puede tener una tabla auxiliar de 0/1 para almacenar las decisiones parciales y recomponer la solución, o
  • A partir de la tabla V obtener la solución (x 1 , x 2 , ..., xn) : partir de la posición V[n, M] y analizar las decisiones que se tomaron para cada objeto i. - Si (V[i, j] = V[i-1, j]) entonces la solución no usa el objeto i , xi= 0. - Si (V[i, j] = V[i-1, j-wi]^ + vi) entonces sí se usa el objeto^ i , xi= 1. - Si (V[i, j] = V[i-1, j-wi] + vi) y (V[i, j] = V[i-1, j]) entonces podemos usar el objeto i o no (existe más de una solución óptima). - (^) Acabar cuando lleguemos a un i=0 ó j=0.
  • (^) ¿Cuál será el tiempo de recomponer la solución?
  • (^) ¿Se cumple el principio de optimalidad?