«Завершите работу» как можно раньше


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 отличается от T , а сумма элементов S и минимального элемента не в S больше , чем L .

    • S и 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.