尽早“完成工作”


20

背景

想象一下,您从事一项令人烦恼的工作。每天早晨,您会收到一系列应该在当天进行的任务。每个任务都有一定的持续时间,一旦开始,就必须一次性完成。您的老板不会容忍闲置,因此,如果有一些任务仍然可以在回家之前完成,则必须处理其中一项(您可以选择其中一项)。相反,如果所有其他任务都需要您加班,那么您就可以早点回家!因此,您的目标是通过明智的安排来最大程度地减少工作时间。

有趣的事实:这是懒惰的官僚调度问题的一种变体,它是NP-hard(来源)。

输入值

您有两个输入:工作日中“时间单位”的数量(正整数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

Answers:


3

果冻,20个字节

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

在线尝试!

TIO的速度足以在60秒的时间内完成最后的测试用例,即使只是勉强完成。

背景

该算法既简单又效率低下:

  1. 我们生成T的所有子集,计算重复数。

  2. 我们过滤子集,仅保留那些满足以下条件之一的子集S:

    • 小号是从不同Ť,和的元素的总和小号和最小元件小号大于大号

    • ST相同。

    现在,已过滤的T(我们称其为T')包含所有仅完成足够工作(甚至有些超时)的任务的列表。

  3. T'中所有S中,选择总和最低的那个。

怎么运行的

Œ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

Pyth,26 25字节

JEhSsMf&gJsT>hS.-QT-JsTyQ

在线尝试。 测试套件。

我无法运行最后两个测试用例(我认为它们在线超时),但所有其他用例都可以运行。这只是基本的暴力解决方案。


1

Ruby,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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.