„Arbeit beenden“ so früh wie möglich


20

Hintergrund

Stellen Sie sich für einen Moment vor, Sie hätten einen nervenaufreibenden Job. Jeden Morgen erhalten Sie eine Sammlung von Aufgaben, die Sie an diesem Tag bearbeiten sollten. Jede Aufgabe hat eine bestimmte Dauer und muss nach dem Start in einem Durchgang erledigt werden. Ihr Chef toleriert keinen Leerlauf. Wenn Sie also noch Aufgaben erledigen können, bevor Sie nach Hause gehen, müssen Sie an einer dieser Aufgaben arbeiten (Sie können auswählen, welche). Umgekehrt, wenn alle verbleibenden Aufgaben Überstunden erfordern, können Sie früh nach Hause gehen! Ihr Ziel ist es daher, durch geschickte Planung die Länge Ihres Arbeitstages zu minimieren.

Unterhaltsame Tatsache: Dies ist eine Variante des Problems der faulen Zeitplanung für Bürokraten , und es ist NP-schwer ( Quelle ).

Eingang

Sie haben zwei Eingaben: die Anzahl der "Zeiteinheiten" in Ihrem Arbeitstag (eine positive Ganzzahl L) und die Auflistung von Aufgaben (ein nicht leeres Array positiver Ganzzahlen T, die die Aufgabendauer darstellen). Sie können in beliebiger Reihenfolge und in einem angemessenen Format abgerufen werden. Das Array Tkann Aufgaben mit einer Dauer von mehr als enthalten L, es wird jedoch garantiert, dass mindestens eine Aufgabe mit einer Dauer von höchstens enthalten ist L.

Ausgabe

Ein gültiger Zeitplan ist eine Teilmenge von Aufgaben S ⊆ T, als solche sum(S) ≤ L, und jede Aufgabe nicht in S(Zählen Multiplizitäten) hat eine Dauer streng mehr als L - sum(S). Ihre Ausgabe soll die kleinstmögliche Summe eines gültigen Zeitplans sein. Mit anderen Worten, Sie müssen die minimale Anzahl von Zeiteinheiten ausgeben, die Sie heute arbeiten müssen.

Beispiel

Betrachten Sie die Eingaben

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

Eine Möglichkeit, Ihren Tag zu planen, besteht darin [4,4], zwei Aufgaben in 8 Zeiteinheiten zu erledigen und 1 Einheit übrig zu haben. Da keine 1-Einheiten-Aufgaben verfügbar sind, können Sie nach Hause gehen. Der Zeitplan [2,5]ist jedoch noch besser: Sie arbeiten für 7 Zeiteinheiten, und alle verbleibenden Aufgaben würden 3 oder mehr Zeiteinheiten in Anspruch nehmen. Der Zeitplan [2,4]ist ungültig, da Sie nach der Arbeit für 6 Zeiteinheiten noch genügend Zeit haben, um die 3-Einheiten-Aufgabe abzuschließen. 7 Einheiten erweisen sich als optimal, daher ist die richtige Ausgabe 7.

Regeln und Wertung

Sie können entweder ein vollständiges Programm oder eine Funktion schreiben. Die niedrigste Byteanzahl gewinnt, und Standardlücken sind nicht zulässig. Es gibt keine Zeitbeschränkung, so dass das brachiale Erzwingen durchaus akzeptabel ist.

Testfälle

Diese sind im Format angegeben 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

Antworten:


3

Gelee, 20 Bytes

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

Probieren Sie es online!

TIO ist schnell genug, um die letzten Testfälle innerhalb des Zeitlimits von 60 Sekunden zu beenden, auch wenn es nur knapp ist.

Hintergrund

Der Algorithmus ist sowohl einfach als auch ineffizient:

  1. Wir generieren alle Teilmengen von T und zählen die Multiplizitäten.

  2. Wir filtern die Teilmengen und behalten nur die Teilmengen S bei, die eines der folgenden Kriterien erfüllen:

    • S unterscheidet sich von T , und die Summe der Elemente von S und dem minimalen Element nicht in S größer ist als L .

    • S und T sind identisch.

    Das gefilterte T (nennen wir es T ' ) enthält jetzt alle Aufgabenlisten, die gerade genug Arbeit leisten (oder sogar Überstunden).

  3. Wählen Sie von allen S in T ' das mit der niedrigsten Summe.

Wie es funktioniert

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

Dies ist eine Brute-Force-Lösung.


1

MATL , 36 Bytes

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

Probieren Sie es online!

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.