"Закінчіть роботу" якомога раніше


20

Фон

Уявіть на мить, що у вас занудлива нудна робота. Кожного ранку вам дають збірку завдань, над якими ви повинні працювати в цей день. Кожне завдання має певну тривалість, і як тільки воно розпочнеться, воно має бути виконане за один раз. Ваш начальник не потерпить простою, тому якщо є завдання, які ви все-таки зможете виконати, перш ніж їхати додому, ви повинні попрацювати над одним із них (ви можете вибрати, яке саме). І навпаки, якщо всі інші завдання вимагатимуть вас понаднормово, ви йдете додому рано! Таким чином, ваша мета - мінімізувати тривалість робочого дня шляхом розумного планування.

Цікавий факт: це один варіант ледачих проблеми планування бюрократ , і це NP-важкою ( джерело ).

Вхідні дані

У вас є два входи: кількість "одиниць часу" у робочий день (додатне ціле число L) та збірка завдань (не порожній масив додатних цілих чисел T, що представляють тривалість завдання). Їх можна прийняти в будь-якому порядку та в будь-якому розумному форматі. Масив Tможе містити завдання, тривалістю більше L, але гарантується, що він містить принаймні одне завдання тривалістю не більше L.

Вихідні дані

Діє графік є підмножиною завдань , S ⊆ Tтаких , що sum(S) ≤ L, і кожна задача не в S( з урахуванням кратності) має тривалість строго більше L - sum(S). Ваш вихід повинен бути найменшою можливою сумою дійсного графіка. Іншими словами, ви повинні вивести мінімальну кількість одиниць часу, якими ви повинні працювати сьогодні.

Приклад

Розглянемо вхідні дані

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

Один із способів планування дня [4,4]: ви закінчите два завдання за 8 одиниць часу і у вас залишилось 1 одиниця. Оскільки задач на 1 одиницю немає, можна піти додому. Однак графік [2,5]ще кращий: ви працюєте на 7 одиниць часу, і тоді всі інші завдання займуть 3 і більше одиниць часу. Графік [2,4]не є дійсним, оскільки, працюючи протягом 6 одиниць часу, у вас все ще буде достатньо часу, щоб виконати завдання на 3 одиниці. 7 одиниць виявляються оптимальними, тому правильний вихід 7.

Правила та оцінка

Ви можете написати або повну програму, або функцію. Виграє найменший кількість байтів, а стандартні лазівки заборонені. Часу немає, тому грубе насильство цілком прийнятно.

Тестові кейси

Вони наведені у форматі 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

Відповіді:


3

Желе, 20 байт

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

Спробуйте в Інтернеті!

TIO досить швидкий, щоб закінчити останні тестові справи протягом 60-секундного обмеження, навіть якщо ледь-ледь.

Фон

Алгоритм є простим і неефективним:

  1. Ми генеруємо всі підмножини T , рахуючи кратність.

  2. Ми фільтруємо підмножини, зберігаючи лише ті підмножини S, які відповідають одному з наступних критеріїв:

    • S відрізняється від Т , а сума елементів S і мінімального елемента НЕ в S більше , ніж L .

    • S і T однакові.

    Відфільтрований T (назвемо це T ' ) тепер містить усі списки завдань, які виконують достатньо роботи (або навіть деякої понаднормової роботи).

  3. З усіх S у T ' виберіть той, який має найменшу суму.

Як це працює

Œ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

Рубін, 124 байти

->(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)
}

Це жорстоке рішення.


1

MATL , 36 байт

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

Спробуйте в Інтернеті!

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.