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

Programación Dinámica (DP)

Instructor: Marcos Villagra Clase #


Escriba: Santiago Acevedo Fecha

1 Maximum Subarray
Dado un arreglo de n enteros, se debe determinar la suma máxima de un subarreglo de
enteros continuos.

Un algoritmo de fuerza bruta debe calcular la suma de todos los subarreglos posibles,
lo cual tomarı́a O(n3 ). Utilizando DP se puede calcular una solución parcial para cada
posición 0 ≤ i < n en el arreglo y almacenar la mejor entre estas. Cada solución parcial
representa el subarreglo máximo que sea un sufijo del subarreglo A[0...i]. Estas sumas se
pueden formular de las siguientes dos maneras:

i
X
S(i) = max { A[x]} (1)
j∈[0,i]
x=j

S(i) = max{S(i − 1) + A[i], A[i], 0} (2)

El planteamiento de la fórmula (1) necesita iterar a través del arreglo por lo menos una
vez, por lo que la complejidad total es de O(n2 ). Por otro lado, la ecuación (2) solo utiliza
valores ya calculados ası́ que este algoritmo, conocido como el algoritmo de Kadane, se
puede realizar en O(n).

1: procedure Max-Subarray(A)
2: sum ← 0
3: resp ← 0
4: for i ← 0 to n − 1 do
5: sum ← sum + A[i]
6: resp ← max{sum, A[i], 0}
7: return resp

Nótese que la fórmula (1) no es una formulación de DP válida, ya que no existe una
definición inductiva de S.

Este problema originalmente fue planteado en dos dimensiones, y la versión unidimen-


sional fue propuesta para entender mejor su estructura. El planteamiento original es el
siguiente: dada una matriz cuadrada de n × n, se desea encontrar una submatriz de suma
máxima.
Una formulación por DP puede considerar la suma máxima entre aquellas sumatrices con
su esquina inferior derecha en (i, j).

X j
i X
S(i, j) = max { A[x, y]}
k∈[0,i]
l∈[0,j] y=k x=l

Cada valor de S(i, j) representa una solución parcial, la cual es valor máximo entre las
sumas obtenidas para cada valor de k y de l. Cada sumatoria representa la suma de la
siguiente submatriz:
 
akl . . . akj
Ak,j,i,j =  ... .. .. 

. . 
ail ... aij

Esta solución tiene un costo de O(n4 ). Sin embargo, existe una variación del algoritmo
de Kadane que se encuentra en O(n3 ).

1: procedure Max-Submatrix(A)
2: max ← 0
3: sum ← 0
4: for lef t ← 0 to n − 1 do
5: S←0
6: for right ← lef t to n − 1 do
7: for i ← 0 to n − 1 do
8: S[i] ← M [i, right]
9: sum ← Max-Subarray(S)
10: if sum > max then
11: max ← sum
12: return max

2 Longest Increasing Subsequence (LIS)


Dado un arreglo de n enteros, determinar la longitud de la subsecuencia creciente más
larga.

Una subsecuencia es un subconjunto de elementos de una secuencia que mantienen su


orden relativo. Esta subsecuencia no necesita ser continua. Por ejemplo, una posible sub-
secuencia creciente más larga es la siguiente:

1 2 8 3 9 6 4 5 7

La siguiente formulación DP calcula la longitud del LIS cuyo último elemento se encuentre
en la posición i, y el mayor entre estos valores tendrá que ser la solución global. Esta solución
se encuentra en O(n2 ).

2
LIS(i) = 1 + max {LIS(j)}
j<i
A[j]<A[i]

3 Problema del mochilero (Knapsack)


Dada una bolsa de capacidad W y n items con pesos w1 , w2 , . . . wn y valores v1 , v2 , . . . vn
de cada item, calcular la combinación de items de máximo valor que puedan entrar en la
bolsa.

El siguiente es un ejemplo en donde n = 4 y W = 10.


Item (i) Peso (wi ) Valor (vi )
1 6 30
2 3 14
3 4 16
4 2 9

Existen dos variedades del problema: una que admite elementos repetidos y otra que
no. En el primer caso, la solución óptima es {1, 0, 0, 2} y tiene un valor total de 48. En el
segundo, la solución optima es {1, 0, 1, 0} y tiene un valor de 46.

3.1 Knapsack con repetición


En esta versión del problema existe una cantidad ilimitada de items y la solución final es
representada como un arreglo de enteros. En la siguiente formulación DP, K(w) representa
el valor máximo con una bolsa de capacidad w ∈ [0, W ] y el valor del resultado óptimo
equivale a K(W ).

K(0) = 0
K(w) = max {K(w − wi ) + vi }
i∈[1,n]

Para calcular K(w) se debe agregar un item a otra solución anterior, es decir se debe
agregar vi a K(w − wi ) donde i representa el ı́ndice del item que fue agregado. Para que la
solución sea optima se elige el valor de i que maximize el valor de K(w). El costo de este
algoritmo se encuentra en O(nW ) ya que hay que iterar por cada uno de los n items y se
deben almacenar un número de soluciones parciales proporcial a W . En ambos casos, la
suma de los pesos puede ser menor a W .

3.2 Knapsack sin reptición


La versión más conocida del problema se conoce como 0–1 Knapsack, debido a que cada
item se selecciona una vez o ninguna y el resultado es representado como un arreglo binario.
La siguiente formulación DP usa K(w, j) para representar el valor máximo con una bolsa
de capacidad w ∈ [0, W ] donde los unicos items disponibles son aquellos en el rango [1, j]
donde j ∈ [1, n].

3
K(0, 0) = 0
K(w, j) = max{K(w − wj , j − 1) + vj , K(w, j − 1)}

Al calcular K(w, j) el algoritmo debe decidir si debe incluir el item j o no. Si este se
incluye se suma vj a K(w − wj , j − 1), y si no se toma el valor anterior de K(w, j − 1). En
ambos casos el item j solo se considera una vez. Al igual que con la versión con repetición,
el costo del algoritmo se encuentra en O(nW ) y el resultado óptimo corresponde a K(W, n).

4 Subset Sum
Dado un entero t y un conjunto finito de enteros A = {a1 , a2 , . . . an }, determinar si
existe un subconjunto S ⊆ A tal que la suma de todos los enteros en S sea igual a t (más
formalmente ΣS = t).

Por ejemplo, para el siguiente conjunto A existe un subconjunto S para t = 30.

A = {11, 7, 3, 5, 17, 1, 10}


S = {7, 5, 17, 1}

El siguiente planteamiento DP define una función Q(i, s) que determina si hay un sub-
conjunto no vacı́o dentro de a1 , . . . ai que suma s. Esta función puede tomar un valor de
verdadero o falso (frecuentemente representados como 1 o 0), los cuales representan la
existencia o no de tal subconjunto.

Q(1, s) = (s ≡ a1 )
Q(i, s) = Q(i − 1, s) ∨ Q(i − 1, s − ai )

En el caso base existe un solo subconjunto posible que contiene a1 , por lo que la funcion
se vuelve verdadera si y solo si s = a1 . Para los otros casos, Q(i−1, s) representa que ai ∈
/S
y Q(i − 1, s − ai ) representa que ai ∈ S, por lo que si uno de estos casos resulta verdadero
entones Q(i, s) tambien es verdadero. La complejidad del algoritmo es de O(nt).

5 Cambio
Dado un valor V y una lista de denominaciones de n monedas M = {m1 , m2 , . . . mn },
determinar el número mı́nimo de monedas que deben usarse para obtener V .

Por ejemplo, para V = 10, n = 2 y M = {1, 5} existen tres conjuntos de monedas, donde
el número mı́nimo es 2.

10 × (1) (a)
5 × (1) + 1 × (5) (b)
2 × (5) (c)

4
En el siguiente planteamiento, C(v) representa el número mı́nimo de monedas para
obtener v. A cada paso, el algoritmo itera a través de cada moneda y busca una solución
optima que corresponda a v − mi . El caso base ocurre cuando v = 0, y si no existe una
solución entoces el número de monedas es infinito. El algoritmo tiene un costo de O(nv).

C(v < 0) = ∞
C(0) = 0
C(v) = 1 + min {C(v − mi )}
i∈[1,n]

6 Traveling Salesman Problem (TSP)


Dadas una lista V = {1, . . . n} de ciudades y una lista E = {(i, j) : i, j ∈ V } de distancias
donde dij = dji representa la distancia entre las ciudades i y j, determinar la longitud de
la ruta más corta que visite todas las ciudades y regrese a la ciudad inicial.

Este problema puede ser descrito mediante un grafo, donde las ciudades son vértices y las
distancias son aristas. Cada solución posible consiste en una permutación de n ciudades,
ası́ que un algoritmo de fuerza bruta que compare cada permutación estará en O(n!).

Para realizar una formulación DP hay que observar que cada segmento continuo del
camino más corto recorre esos vértices de la manera más corta posible. Dados un sub-
conjunto S ⊆ {v2 , . . . vn } y un vértice j ∈ S, la función D(S, j) representa la longitud del
camino más corto desde 1 hasta j que visite todos los vértices en S una vez y no visite
ningún otro (el vértice de salida no cuenta).

C(∅, 1) = 0
C(S, j) = min{C(S − {j}, i) + dij }
i∈S
i6=j

El caso base es aquel en donde S esta vacı́o y el vértice de destino es 1. De caso contrario,
para hallar C(S, j) se elige un vértice penúltimo i tal que la longitud del camino de 1 hasta
i más la distancia entre i y j sea mı́nima. Para hallar el resultado final se debe calcular
C(V, 1) de la misma manera, el cual es el único caso donde el recorrido puede terminar en
1 además del caso base.

1: procedure TSP-Shortest(S)
2: C({}, 1) ← 0
3: for s ← 1 to n − 1 do
4: for all S ⊆ {2, . . . n}, |S| = s do
5: for all j ∈ S do
6: C(S, j) ← mini∈S−{j} {C(S − {j}, i) + dij }
7: return min2≤j≤n {C({2, . . . , n}, j) + dj1 }

5
Este algoritmo se conoce como el algoritmo Held-Karp y tiene un costo temporal O(n2 2n ).

7 Distancia de Edición
Dadas dos cadenas x = x1 . . . xn y y = y1 . . . ym , la distancia de edición E entre x e y se
define como el número mı́nimo de inserciones, borrados o sustituciones para transformar x
en y.
La idea de DP para calcular la distancia de edición es comparando prefijos de x e y de
derecha a izquierda. Consideremos los prefijos x1 . . . xi e y1 . . . yj . Denotamos por E(i, j)
como la distancia de edición entre x1 . . . xi e y1 . . . yj . Aquı́ tenemos dos casos para analizar.

(1) Si xi = yj , entonces ignoramos los últimos caracteres de la derecha y resolvemos


recursivamente x1 . . . xi−1 e y1 . . . yj−1 .

(2) Si xi 6= yj , entonces tenemos tres opciones: insertamos un caracter en x para que sea
igual a yj , borramos xi , o sustituimos xi por yj .

Caso (1). Como xi = yj , entonces resolvemos recursivamente para x1 . . . xi−1 e y1 . . . yj−1 .


Porque xi = yy y no hace falta aplicar ninguna operación de edición, entonces tenemos que
la distancia de edición E(i, j) = E(i − 1, j − 1).
Caso (2). Como xi 6= yj , tenemos 3 subcasos que analizar.

(a) Insertar un caracter en x1 . . . xi−1 . El caracter que se inserta debe ser igual a yj .
Esto hace que x1 . . . xi xi+1 , con xi+1 = yj y entonces los ultimos caracteres de ambos
prefijos coinciden. Por lo tanto, nos queda verificar recursivamente la distancia de
edición entre x1 . . . xi e y1 . . . yj−1 . Tenemos entonces que E(i, j) = 1 + E(i, j − 1).

(b) Borrar un caracter en x1 . . . xi . Al borrar el último caracter nos queda la cadena


x1 . . . xi−1 , y por lo tanto, nos queda verificar recursivamente la distancia de edición
entre x1 . . . xi−1 e y1 . . . yj . Tenemos entonces que E(i, j) = 1 + E(i − 1, j).

(c) Sustituir un caracter en x1 . . . xi−1 . Al sustituir el último caracter tenemos que


x1 . . . xi−1 yj , y por lo tanto, los ultimos caracteres coinciden y nos queda verificar re-
cursivamente la distancia de edición entre x1 . . . xi−1 e y1 . . . yj−1 . Tenemos entonces
que E(i, j) = 1 + E(i − 1, j − 1).

En el caso (2) ¿cómo sabemos cual operación hacer? No lo podemos saber, y por lo tanto,
debemos de probar las tres operaciones y elegir la más barata. Entonces la formulación DP
para la distancia de edición es

 1 + E(i, j − 1)
E(i, j) = min 1 + E(i − 1, j)
δij + E(i − 1, j − 1)

donde δij = 1 si xi 6= xj y δij = 0 is xi = yj .

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