# TDA | Practica 1 ejercicio 8
$\textbf{Cortes Económicos}$
$\text{8. Debemos cortar una vara de madera en varios lugares predeterminados. Sabemos que el costo de realizar un corte en una madera de longitud } \ell \text{ es } \ell \text{ (y luego de realizar ese corte quedarán 2 varas de longitudes que sumarán } \ell \text{). Por ejemplo, si tenemos una vara de longitud 10 metros que debe ser cortada a los 2, 4 y 7 metros desde un extremo, entonces los cortes se pueden realizar, entre otras maneras, de las siguientes formas:}$
$\text{Primero cortar en la posición 2, después en la 4 y después en la 7. Esta resulta en un costo de } 10 + 8 + 6 = 24 \text{ porque el primer corte se hizo en una vara de longitud 10 metros, el segundo en una de 8 metros y el último en una de 6 metros.}$
$\text{Cortar primero donde dice 4, después donde dice 2, y finalmente donde dice 7, con un costo de } 10 + 4 + 6 = 20, \text{ que es menor.}$
$\text{Queremos encontrar el mínimo costo posible de cortar una vara de longitud } \ell.$
$\text{(a) Convencerse de que el mínimo costo de cortar una vara que abarca desde } i \text{ hasta } j \text{ con el conjunto } C \text{ de lugares de corte es } j - i \text{ más el mínimo, para todo lugar de corte } c \text{ entre } i \text{ y } j, \text{ de la suma entre el mínimo costo desde } i \text{ hasta } c \text{ y el mínimo costo desde } c \text{ hasta } j.$
$\text{(b) Escribir matemáticamente una formulación recursiva basada en (a). Explicar su semántica e indicar cuáles serían los parámetros para resolver el problema.}$
$\text{(c) Diseñar un algoritmo de PD y dar su complejidad temporal y espacial auxiliar. Comparar cómo resultaría un enfoque top-down con uno bottom-up.}$
$\text{(d) Supongamos que se ordenan los elementos de } C \text{ en un vector cortes y se agrega un 0 al principio y un } \ell \text{ al final. Luego, se considera que el mínimo costo para cortar desde el } i\text{-ésimo punto de corte en cortes hasta el } j\text{-ésimo punto de corte será el resultado buscado si } i = 1 \text{ y } j = |C| + 2.$
$\text{I) Escribir una formulación recursiva con dos parámetros que esté basada en (d) y explicar su semántica.}$
$\text{II) Diseñar un algoritmo de PD, dar su complejidad temporal y espacial auxiliar y compararlas con aquellas de (c). Comparar cómo resultaría un enfoque top-down con uno bottom-up.}$
## Resolución
## a)
- Queremos optimizar el costo, o sea que sea lo mínimo posible.
- Hay que buscar el minimo para todo punto del conjunto estando acotado por i, y j, siendo i el inicio y j el fin.
- Considerar todas las maneras posibles de realizar los cortes y elegir la que cueste menos
## b)
- Sea $C$ un conjunto de cortes a realizar sobre la vara $\ell_i$, $C_i$ un corte especifico en este conjunto $C =$ {$c_1,c_2,...c_n$} y $0<c_1<c_2<...<c_n<\ell$ el costo de realizar un corte sobre la vara de longitud $\ell$ es $\ell$
$C_0 = 0 \\
C_{n+1} = \ell \\
MC(i, j) = \begin{cases}
0 & \text{si } j = i+1 \\
\min_{i < k < j} \left( MC(i, k) + MC(k, j) + (C_j - C_i) \right) & \text{si } j > i+1
\end{cases}$
## c-d)
### Enfoque top-down
```python
from typing import List
def M(longitud: int, cortes: List[int]) -> int:
cortes = [0] + cortes + [longitud] # Como dice el inciso d
memo = {}
def costoMinimo(i: int, j: int) -> int:
if j <= i + 1:
return 0
if (i, j) in memo: # Caso base si el resultado ya está memoizado
return memo[(i, j)]
costoMin = float('inf')
for k in range(i + 1, j): # Paso recursivo
costoActual = costoMinimo(i, k) + costoMinimo(k, j) + (cortes[j] - cortes[i])
costoMin = min(costoMin, costoActual)
memo[(i, j)] = costoMin # Guardo resultado en memoria
return costoMin
# realiza la llamada inicial a la función recursiva
return costoMinimo(0, len(cortes) - 1)
# Ejemplo de uso
longitudVara = 10
cortes = [2, 4, 7]
print(M(longitudVara, cortes))
```
## Arbol
![](https://apuntes.grunt.ar/uploads/f788100a-0009-4c2e-8504-4f8937ab18e5.jpg)
#### Idea de lo que sería el arbol con memoización.
![](https://apuntes.grunt.ar/uploads/6b2aa25a-363c-4f74-bea3-f85d4f8f9171.png)
- En realidad cada nodo tendría una cierta cantidad de aristas por la iteración de $k$
### COMPLEJIDAD
- Eric:
- La cantidad de subproblemas unicos es ${|C|}\choose{2}$.
- $\frac{|C|}{2!(|C|-k)}$ $\leq$ $|C|^2$ Entonces podemos tomar esta cota.
- Entonces podemos decir que la cantidad de nodos unicos van a ser $|C|^2$.
- Ahora: Hay dos llamadas recursivas por cada iteración de k.
- Esto significa que en peor caso va a recorrer la totalidad en cada iteración que es $2 \times |C|$
- Entonces sabemos que:
- #NodosUnicos ~ $|C|^2$
- #NodosMemo ~ $O(1)$
- #HijosDeNodosUnicos ~ $2 \times |C| \times |C|^2$ = $|C|^3$
- max(#NodosUnicos, #NodosMemo, #HijosDeNodosUnicos) = $|C|^3|
- $\Rightarrow$ $\therefore$ $O(n^3)$
- ~~Tengo entendido que hablando de complejidad temporal por cada hijo se abren dos hojas excepto si ya está precalculado, lo cual iría a $memo$~~
- ~~A simple vista veo una complejidad de $O(n^2)$~~
- ~~Pero tengo entendido que es cuadratica y no lo veo del todo.~~
- ~~Para n cortes hay O(n²) pares (i,j) posibles, pero para cada subproblema toma ua decisión sobre cada punto de corte posible (i,j) lo cual es proporcoinal a n.~~
- ~~La complejidad de un problema unico es $O(n)$~~
### Complejidad espacial
- ToDo
- Estimo cuadratica