Se dice que la codicia no es solo una debilidad de dragones y hombres: bien entendida, también puede ser una estrategia. Este sendero recorre tres problemas donde la mejor decisión en cada paso (la más inmediata, la más voraz) resulta ser también la mejor decisión posible para el problema completo. No hace falta mirar atrás ni reconsiderar lo ya elegido: alcanza con, en cada instante, tomar lo mejor que el momento ofrece.

Vas a conocer a un dragón que no puede cargar más de lo que su fuerza le permite, a un consejero que debe repartir un día que no alcanza para todos, y a esa misma bestia bajo la montaña, ahora del otro lado, intentando defenderse en lugar de atacar. En los tres casos, ordenar bien antes de decidir es la mitad del problema resuelto.


El Tesoro de Smaug

Dificultad: ★☆☆☆☆

Tras siglos dormido sobre su tesoro, Smaug debe abandonar temporalmente su guarida en la Montaña Solitaria: los enanos han comenzado a horadar un nuevo túnel y el dragón, prudente a su manera, prefiere trasladar lo que pueda antes de que lo descubran. El problema es que ni siquiera un dragón puede cargar todo el oro de Erebor de una sola vez: sus garras y su lomo soportan, como mucho, un peso máximo . Ante Smaug hay sacos de tesoro, cada uno con su propio peso y su propio valor (las esmeraldas pesan poco y valen mucho, el oro en bruto pesa como el oro en bruto). A diferencia de un ladrón cualquiera, Smaug puede desgarrar un saco con sus garras y llevarse solo una fracción de su contenido, si eso le permite aprovechar mejor el espacio que le queda.

Enunciado

El problema es la variante fraccionaria de la mochila: dada una capacidad y sacos, cada uno con peso y valor , se puede tomar cualquier fracción de cada saco, no solo el saco entero, maximizando sujeto a .

  1. Explicar por qué ordenar los sacos por su razón valor/peso , de mayor a menor, y tomarlos en ese orden hasta completar la capacidad , produce siempre una solución óptima en la variante fraccionaria. Justificar con un argumento de intercambio: ¿qué pasaría si Smaug tomara primero una unidad de peso de un saco con menor razón valor/peso, existiendo todavía unidades disponibles de un saco con mayor razón?

  2. Diseñar el algoritmo paso a paso, indicando qué ocurre cuando el peso restante de la capacidad es menor que el peso completo del siguiente saco en el orden.

  3. Trazar a mano la ejecución con capacidad y los siguientes sacos:

    SacoPeso ()Valor ()
    Esmeraldas1060
    Oro amonedado20100
    Oro en bruto30120
    Gemas talladas1590

    Mostrar el orden elegido, qué fracción de cada saco toma Smaug y el valor total transportado.

  4. Determinar la complejidad temporal del algoritmo en función de , identificando qué paso domina el costo total.

Abrir artículo


El Consejo de Elrond

Dificultad: ★★★☆☆

Rivendel se ha llenado de visitantes. Elfos, enanos, hombres y hasta algún mago han llegado con noticias urgentes y quieren ser escuchados por el Consejo antes de que termine el día. Cada delegación necesita hablar durante un intervalo específico (algunas deben esperar a que termine cierto rito, otras necesitan la luz del atardecer para desplegar sus mapas) y ese intervalo no se puede interrumpir ni negociar. Elrond preside el Consejo, pero el día tiene las horas que tiene: dos delegaciones no pueden hablar si sus intervalos se superponen, y una vez que una delegación empieza a exponer hay que dejarla terminar. Elrond quiere decidir a cuáles delegaciones va a recibir, de forma de escuchar a la mayor cantidad posible antes de que caiga la noche.

Enunciado

Dadas delegaciones, cada una con un intervalo de inicio y fin, se busca el subconjunto más grande de intervalos mutuamente compatibles (sin superposición).

  1. Explicar por qué ordenar las delegaciones por su hora de finalización (y no por su hora de inicio , ni por la duración de su exposición) y elegir en forma ávida, en cada paso, la primera delegación compatible con las ya elegidas, garantiza el número máximo de delegaciones atendidas. Construir un ejemplo concreto donde ordenar por duración (las exposiciones más cortas primero) elija menos delegaciones que el óptimo.

  2. Diseñar el algoritmo paso a paso.

  3. Trazar a mano la ejecución con las siguientes delegaciones:

    DelegaciónInicioFin
    Hombres de Gondor06
    Istari89
    Enanos de Erebor35
    Hobbits de la Comarca57
    Dúnedain del Norte610
    Elfos de Lórien14
    Rohirrim59

    Indicar en qué orden se evalúan las delegaciones y cuáles quedan finalmente aceptadas.

  4. Determinar la complejidad del algoritmo en función de , identificando qué paso domina el costo total.

Ver solución

1. Por qué ordenar por fin de intervalo

Argumento de intercambio (breve): supongamos que una solución óptima no elige, entre todas las delegaciones, a la que termina primero (llamémosla , con fin mínimo). Sea la primera delegación que sí eligió esa solución óptima. Como y no se superpone con ninguna otra elegida (termina antes que cualquier otra que empiece después de ), podemos reemplazar por sin perder compatibilidad y sin reducir la cantidad de delegaciones aceptadas. Repitiendo este intercambio se llega a que siempre existe una solución óptima que contiene a la delegación de fin más temprano. Por eso conviene elegirla primero, descartar todo lo que se superponga con ella, y repetir el mismo razonamiento sobre lo que queda: es un problema idéntico, pero más chico.

Por qué falla ordenar por duración: una delegación corta puede “tapar” a dos delegaciones más largas que sí serían compatibles entre sí. Contraejemplo mínimo:

DelegaciónIntervaloDuración
P(0, 4)4
Q(3, 5)2
R(4, 8)4

Ordenando por duración se elige primero Q (duración 2), que se superpone con P y con R, así que quedan descartadas ambas → solo 1 delegación atendida.
Ordenando por fin, en cambio, se elige P (fin 4) y después R (fin 8, compatible porque empieza justo en 4) → 2 delegaciones atendidas, que es el óptimo real.

2. Diseño del algoritmo

  1. Ordenar las delegaciones por su hora de fin, de menor a mayor.
  2. Inicializar ultimo_fin = -∞ y aceptadas = [].
  3. Para cada delegación en ese orden:
    • Si ultimo_fin: aceptarla (agregar a aceptadas) y actualizar ultimo_fin = f_i.
    • Si no, descartarla (se superpone con la última aceptada).
  4. Devolver aceptadas.

3. Traza a mano

Datos originales:

DelegaciónInicioFin
Hombres de Gondor06
Istari89
Enanos de Erebor35
Hobbits de la Comarca57
Dúnedain del Norte610
Elfos de Lórien14
Rohirrim59

Paso 1: ordenar por fin (Istari y Rohirrim empatan en fin = 9; el orden entre ellos no afecta el resultado):

OrdenDelegaciónInicioFin
1Elfos de Lórien14
2Enanos de Erebor35
3Hombres de Gondor06
4Hobbits de la Comarca57
5Rohirrim59
6Istari89
7Dúnedain del Norte610

Paso 2: recorrido ávido (ultimo_fin inicial ):

DelegaciónInicio¿Inicio ≥ último fin?Decisiónultimo_fin tras el paso
Elfos de Lórien1Aceptada4
Enanos de Erebor3 → noRechazada4
Hombres de Gondor0 → noRechazada4
Hobbits de la Comarca5Aceptada7
Rohirrim5 → noRechazada7
Istari8Aceptada9
Dúnedain del Norte6 → noRechazada9

Resultado: Elrond escucha a Elfos de Lórien (1,4), Hobbits de la Comarca (5,7) e Istari (8,9): 3 delegaciones, y no existe forma de encajar una cuarta sin superposición.

4. Complejidad

  • Ordenar las delegaciones por fin: .
  • Recorrer la lista ordenada una sola vez, con trabajo constante por delegación: .

Total: , dominado por el paso de ordenamiento.

Abrir artículo


Las Defensas de Erebor

Dificultad: ★★★★★

Los años pasaron y Smaug, ahora del otro lado del problema, necesita defender lo que le queda de tesoro. La Montaña tiene accesos conocidos (puertas viejas, chimeneas de ventilación, grietas que los enanos abrieron y nunca sellaron del todo) y cada uno es vulnerable solamente durante un intervalo de tiempo determinado: la puerta oeste solo puede forzarse mientras dura cierto relevo, cierta grieta solo es practicable mientras la luna ilumina cierta piedra, y así con cada acceso. Smaug quiere ubicar trampas o centinelas que actúen en un instante puntual (no durante un intervalo, sino en un momento exacto) de forma que cada acceso quede cubierto por al menos una trampa durante su ventana de vulnerabilidad. Colocar cada trampa tiene un costo, así que Smaug quiere usar la menor cantidad posible.

Enunciado

Dados accesos, cada uno con un intervalo de vulnerabilidad , se busca el menor conjunto de puntos tal que todo intervalo contenga al menos un .

Este problema es distinto al de el consejo de elrond: ahí se buscaba elegir la mayor cantidad de intervalos compatibles entre sí; acá se busca elegir la menor cantidad de puntos que, entre todos, toquen a todos los intervalos dados (un punto ubicado dentro de un intervalo lo cubre).

  1. Explicar la estrategia voraz: ordenar los accesos por su instante de finalización de vulnerabilidad, de menor a mayor; colocar una trampa exactamente en el instante de finalización del primer acceso sin cubrir; descartar todos los accesos que esa trampa cubre; y repetir con los accesos restantes. Justificar por qué conviene colocar la trampa en el extremo final del intervalo, y no en cualquier otro punto interior, para maximizar la cantidad de accesos adicionales que esa misma trampa puede llegar a cubrir.

  2. Argumentar, aunque sea de forma intuitiva, por qué ninguna estrategia puede cubrir todos los accesos con menos trampas que las que propone el algoritmo voraz (pensar qué pasaría si una solución óptima no incluyera ese primer punto de finalización, ni ningún punto anterior a él, para cubrir al acceso que vence primero).

  3. Trazar a mano la ejecución con los siguientes accesos, dados como intervalos de vulnerabilidad (inicio, fin):

    AccesoInicioFin
    Puerta Oeste14
    Chimenea Sur26
    Grieta del Cuervo47
    Túnel de los Enanos59
    Puerta Principal810
    Escalinata Oculta912
    Ventana de la Guardia1113

    Mostrar en qué orden se procesan los accesos, dónde se coloca cada trampa y qué accesos cubre cada una.

  4. Determinar la complejidad del algoritmo en función de , identificando qué paso domina el costo total.

Abrir artículo


Si este sendero te dejó pensando en cómo decidir rápido sin arrepentirse después: la misma idea, elegir siempre lo mejor disponible en cada paso, ordenando bien antes de mirar nada más, es el corazón de algoritmos como Kruskal y Prim (para construir la red más barata posible), Dijkstra (para encontrar el camino más corto) y la codificación de Huffman (para comprimir información sin perder nada). En todos esos casos, igual que en la mochila de Smaug, el Consejo de Elrond o las defensas de Erebor, el desafío no es probar todas las combinaciones posibles: es encontrar el criterio de orden correcto, el que garantiza que decidir de a un paso por vez alcanza para llegar a la mejor solución global.