"Termine el trabajo" lo antes posible


20

Antecedentes

Imagine por un momento que tiene un trabajo aburrido y abrumador. Cada mañana, se le da una colección de tareas en las que debe trabajar ese día. Cada tarea tiene una duración determinada y, una vez iniciada, debe completarse de una vez. Su jefe no tolerará el ralentí, por lo que si hay tareas que aún puede completar antes de irse a casa, debe trabajar en una de ellas (puede elegir cuál). Por el contrario, si todas las tareas restantes requieren que trabajes horas extras, ¡puedes ir a casa temprano! Por lo tanto, su objetivo es minimizar la duración de su jornada laboral mediante una programación inteligente.

Dato curioso: esta es una variante del problema de programación del burócrata perezoso , y es NP-hard ( fuente ).

Entrada

Tiene dos entradas: el número de "unidades de tiempo" en su jornada laboral (un entero positivo L) y la colección de tareas (una matriz no vacía de enteros positivos T, que representa la duración de las tareas). Se pueden tomar en cualquier orden y en cualquier formato razonable. La matriz Tpuede contener tareas con una duración superior a L, pero se garantiza que contiene al menos una tarea con una duración máxima L.

Salida

Un cronograma válido es un subconjunto de tareas S ⊆ Ttales que sum(S) ≤ L, y cada tarea que no está en S(contando multiplicidades) tiene una duración estrictamente superior a L - sum(S). Su salida será la suma más pequeña posible de un horario válido. En otras palabras, debe generar la cantidad mínima de unidades de tiempo que debe trabajar hoy.

Ejemplo

Considere las entradas

L = 9
T = [3,4,4,4,2,5]

Una forma de programar su día es [4,4]: finaliza dos tareas en 8 unidades de tiempo y le queda 1 unidad. Como no hay tareas de 1 unidad disponibles, puede irse a casa. Sin embargo, el cronograma [2,5]es aún mejor: trabajas durante 7 unidades de tiempo, y luego todas las tareas restantes tomarían 3 o más unidades de tiempo. El cronograma [2,4]no es válido, ya que después de trabajar durante 6 unidades de tiempo, aún tendría tiempo suficiente para terminar la tarea de 3 unidades. 7 unidades resultan ser óptimas, por lo que la salida correcta es 7.

Reglas y puntaje

Puede escribir un programa completo o una función. El conteo de bytes más bajo gana, y las lagunas estándar no se permiten. No hay límite de tiempo, por lo que el forzamiento bruto es perfectamente aceptable.

Casos de prueba

Estos se dan en el formato L T -> output.

 1 [1,2] -> 1
 6 [4,1] -> 5
 7 [7,7,9] -> 7
 9 [3,4,4,4,2,5] -> 7
20 [6,2,3,12,7,31] -> 17
42 [7,7,7,7,8,8,8] -> 36
42 [7,7,7,7,7,8,8,8] -> 35
42 [7,7,7,7,7,7,8,8,8] -> 36
16 [1,2,3,4,5,6,7,8,9,10] -> 13
37 [15,27,4,1,19,16,20,26,29,18] -> 23
22 [24,20,8,8,29,16,5,5,16,18,4,9] -> 18
80 [10,22,11,2,28,20,27,6,24,9,10,6,27,2,15,29,27] -> 71
59 [26,28,5,4,7,23,5,1,9,3,7,15,4,23,7,19,16,25,26] -> 52

Respuestas:


3

Jalea, 20 bytes

³œ-;⁴Ṃ;¹S>⁴
ŒPÇÐfS€Ṃ

Pruébalo en línea!

TIO es lo suficientemente rápido como para terminar los últimos casos de prueba dentro de su límite de tiempo de 60 segundos, aunque sea apenas.

Antecedentes

El algoritmo es simple e ineficiente:

  1. Generamos todos los subconjuntos de T , contando multiplicidades.

  2. Filtramos los subconjuntos, manteniendo solo aquellos subconjuntos S que satisfacen uno de los siguientes criterios:

    • S es diferente de T , y la suma de los elementos de S y el elemento mínimo no en S es mayor que L .

    • S y T son idénticos.

    La T filtrada (llamémosla T ' ) ahora contiene todas las listas de tareas que hacen el trabajo suficiente (o incluso algunas horas extra).

  3. De todos los S en T ' , elija el que tenga la suma más baja.

Cómo funciona

ŒPÇÐfS€Ṃ     Main link. Left input: T (list). Right input: L (integer).

ŒP           Powerset; generate all subsets of T.
   Ðf        Filter them...
  Ç            applying the helper link.
     S€      Compute the sum of each kept subset.
       Ṃ     Take the minimum.

³œ-;⁴Ṃ;¹S>⁴  Helper link. Input: A (subset of T)

³œ-          Multiset subtraction; remove the elements of A from T, counting
             multiplicities.
   ;⁴        Append L to the resulting list.
     Ṃ       Take the minimum.
             If S == T, the difference was empty and the minimum is L.
      ;¹     Prepend the minimum to A.
        S    Compute the sum.
         >⁴  Compare it with L.
             If S == T, the comparison will return 1.


1

Ruby, 124 bytes

->(m,s){
f=proc{|l,t|t.reject!{|x|x>l}
(0...(t.size)).map{|x|
f.call(l-t[x],t[0,x]+t[(x+1)..-1])
}.max||l
}
m-f.call(m,s)
}

Esta es una solución de fuerza bruta.


1

MATL , 36 bytes

iTFinZ^!"2G@2#)sXKt1G>~wb+lG>A*?KhX<

Pruébalo en línea!

i           % input number L
TF          % array [true, false]
in          % input array T. Get its length
Z^!         % Cartesian power and transpose. Each column is a selection from T
"           % for each selection
  2G@2#)    %   take non-selected and then selected tasks
  sXK       %   sum of selected tasks. Copy to clipboard K
  t1G>~     %   duplicate. Is sum of selected tasks <= L?
  wb        %   swap, rotate
  +         %   sum of selected tasks plus each non-selected task
  lG>A      %   are all of those numbers greater than L?
  *         %   are both conditions met?
  ?         %   if so
    Kh      %     paste current minimum (or initially L), append new value
    X<      %     compute new minimum
            %   end if implicitly
            % end for each implicitly
            % display stack implicitly
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.