Solución parcial 2

Anuncio
Solución parcial 2
Dante
9 de junio de 2009
Ejercicio 1
El profesor Germán volcó cerveza en el teclado de su laptop, y se arruinaron
todas las teclas que denotan signos de puntuación, además de la barra espaciadora. Ayer me escribió un mail cuyo cuerpo era:
AdjuntoejerciciosparaelparcialSaludos
Dado un Germán-mensaje como una cadena s[1..n], se le pide determinar si
el mensaje puede reconstruirse como una secuencia válida de palabras de nuestro idioma. Por ejemplo, el mensaje anterior es una secuencia válida, pues las
palabras “Adjunto”, “ejercicios”, “para”, “el”, “parcial”, “Saludos” son todas
válidas. Un ejemplo de secuencia no válida es holatychau.
Para ayudarse, usted contará con un diccionario, que será representado mediante una función booleana dic : String → Bool , que determina si una secuencia de caracteres está en el diccionario. Es decir,
true si s[p..q] es válida
dic(s[p..q]) =
false si no
Solución
(a) La idea es ir leyendo la cadena de derecha a izquierda, y ver cuándo la subcadena s[j..n] se puede rearmar como un mensaje. Cuando j = 1, obtenemos
la respuesta.
Supongamos que tenemos la cadena s[j..n] ¿Cuándo es válida?
El caso más fácil de responder es si dic(s[j..n]) = true, pues la secuencia
completa es una palabra y no hace falta intercalar espacios.
Si s[j..n] no está en el diccionario, entonces necesariamente existe una posición donde hay que poner un espacio. Tenemos que verificar
Que se puede armar una palabra s[j..k] que está en el diccionario
Que la secuencia que queda, s[k + 1..n] es una Germán-mensaje válido
Todo esto para algún j ≤ k < n.
La formulación recursiva es entonces:
true
G(s[j..n]) =
∃k ∈ {j, . . . , n − 1} dic(s[j..k]) ∧ G(s[k + 1..n])
1
si dic(s[j..n]) = true
en caso contrario
(b) El algoritmo de programación dinámica serı́a más o menos ası́:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
procedure Ger ( s )
n ← length ( s )
tabla [ 1 . . n ] ← { false , . . . , false }
f o r j ← n downto 1 do
i f d i c ( s [ j . . n ] ) then
t a b l a [ j ] ← true
else
f o r k ← j to n − 1 do
i f d i c ( s [ j . . k ] ) ∧ t a b l a [ k+1] then
t a b l a [ j ] ← true
i f tabla [ 1 ]
r e t u r n true
else
return false
(c) Es fácil ver que la condición en la lı́nea 9 se evalúa 1+2+. . . n−1 = n×(n−1)
2
veces, y asumiendo que la complejidad de dic es Θ(1), la complejidad de Ger
resulta Θ(n2 ). Se deja un análisis más detallado como ejercicio.
Ejercicio 2
Sea X un conjunto finito de intervalos cerrados de la recta real. Diremos que
un conjunto de puntos P atraviesa a X si cada intervalo de X contiene al menos
un punto en P . Por ejemplo, en la figura vemos un conjunto de intervalos X,
y un conjunto P de cuatro puntos (vistos como barras verticales) que atraviesa
a X.
Dadas dos secuencias L[1..n] y R[1..n], que representan los extremos izquierdos y derechos de n intervalos, estamos interesados en encontrar un conjunto
de mı́nimo cardinal que lo atraviese.
Por ejemplo, dadas las secuencias
L = h4, 5, 0, 11, 1, 10, 5i
R = h7, 10, 3, 14, 5, 13, 9i
Los intervalos serán X = {[4, 7], [5, 10], [0, 3], [11, 14], [1, 5], [10, 13], [5, 9]}, y
un conjunto que atraviesa X es P = {2, 6, 11}.
(a) Describa una estrategia greedy que encuentre una solución al problema
(b) Demuestre que su estrategia es óptima
2
Solución
(a) Tomemos todos los intervalos. Imaginemos un conjunto P que cumple con
las condiciones, y pensemos en su punto más a la izquierda (un análisis
similar vale para el punto más a la derecha).
Para intentar cubrir lo más posible, podemos pensar que nos conviene que
este punto esté lo más a la derecha posible, porque ası́ tiene más posibilidades de cubrir más intervalos. Por supuesto, no puede ser tan a la derecha
como uno quiera, porque va a llegar un punto en que va a dejar de cubrir
algún intervalo
Pregunta: ¿Cuándo sucede esto?
Respuesta: Cuando el punto llega al final del primer intervalo, donde llamamos primer intervalo al que termina primero, leyendo de izquieda a
derecha (es decir, aquel de menor valor para R).
A ver si se entiende con un ejemplo: Para la figura del enunciado, podemos
correr a la derecha la primer barra vertical, siempre y cuando no pase el
final de ningún intervalo.
Nuestra estrategia greedy será entonces:
(1) Ordenar los intervalos de forma creciente de acuerdo a sus extremos
derechos
(2) Mientras queden intervalos sin cubrir,
elegir como punto para agregar a P el extremo derecho del primer
intervalo
“tachar” todos los intervalos que son cubiertos por este punto
¡Es la misma solución que para el problema de las tareas!
Para el ejemplo dado en el problema, luego de ordenar queda:
X = {[0, 3], [1, 5], [4, 7], [5, 9], [5, 10], [10, 13], [11, 14]}
En el primer paso, elegimos el punto 3, y tachamos dos intervalos: [0, 3]
y [1, 5]. Ahora los intervalos que quedan son:
X = {[4, 7], [5, 9], [5, 10], [10, 13], [11, 14]}
Elegimos ahora el punto 7, y tachamos [4, 7], [5, 9] y [5, 10]. Los intervalos que quedan son:
X = {[10, 13], [11, 14]}
elegimos el punto 13 y tachando ya no quedan intervalos. Juntando
todo, tenemos que el conjunto P que atraviesa X es P = {3, 7, 11}
(b) Demostremos que es óptima. Daremos las ideas principales, dejando los
detalles para el lector.
3
Seguridad de la estrategia greedy
Debemos ver que el punto que elegimos en cada paso forma parte de una
solución óptima.
Supongamos que tenemos los intervalos X = {xj , . . . , xn }, donde inicialmente j = 1. Debemos ver que existe una solución optima que tiene al
punto R[j] (extremo derecho del primer intervalo).
Sea P = {p1 , . . . , pk } una solución óptima al problema, y pi el mı́nimo de
P.
Observemos que pi ≤ R[j], pues xj debe ser atravesado, y por lo tanto debe
existir un punto en P que esté a la izquierda de R[j]. Como pi es el más a
la izquierda de P , concluimos que pi está a la izquierda de R[j].
Tomemos ahora P 0 = P \ {pi } ∪ {R[j]} ¿Es P 0 solución óptima para X?
P 0 tiene la misma cantidad de elementos que P , por lo que si es solución, es óptima
R[j] tiene que atravesar al menos tantos intervalos como pi : Si no fuese
ası́, es porque hay algún intervalo que pi atravesaba y R[j] no; pero
esto significa que el final de este intervalo está a la izquierda de R[j], lo
cual es absurdo, pues R[j] era el final “más a la izquierda” que habı́a.
Por lo tanto P 0 es solución para X.
Concluimos entonces que R[j] pertenece a un óptimo para el problema.
Subestructura óptima
Sea X = {xj , . . . , xn } un conjunto de intervalos ordenados, R[j] el extremo
derecho de xj , y
X 0 = {xk ∈ X | L[k] > R[j]}
Es decir, X 0 es el subproblema que queda luego de elegir R[j].
Tenemos que ver que, si P 0 = {p1 , . . . , pm } es solución óptima de X 0 , entonces P = P 0 ∪ {Rj } es solución óptima de X.
Supongamos que no, entonces existe Q solución de X tal que |Q| < |P |.
Sea qi el mı́nimo de Q. Como Q es solución de X, necesariamente tiene que
ser qi < R[j], pues Q tiene que atravesar xj . De esto se deduce que qi no
atraviesa ningún intervalo en X 0 (ya que en X 0 todos empiezan a la derecha
de R[j]).
Por lo tanto, Q0 = Q \ {qi } tiene que atravesar X 0 .
Pero si esto es cierto, encontramos un conjunto Q0 que es solución de X 0 y
además |Q0 | = |Q| − 1 < |P | − 1 = |P 0 |. Absurdo, pues P 0 era óptimo de
X 0.
4
Descargar