"Selesaikan pekerjaan" sedini mungkin

20

Latar Belakang

Bayangkan sejenak bahwa Anda memiliki pekerjaan yang menjemukan. Setiap pagi, Anda diberi koleksi tugas yang harus Anda kerjakan pada hari itu. Setiap tugas memiliki durasi tertentu, dan sekali dimulai, itu harus diselesaikan dalam sekali jalan. Bos Anda tidak akan mentolerir pemalasan, jadi jika ada tugas yang masih bisa Anda selesaikan sebelum pulang, Anda harus mengerjakan salah satu dari mereka (Anda dapat memilih yang mana). Sebaliknya, jika semua tugas yang tersisa mengharuskan Anda bekerja lembur, Anda harus pulang lebih awal! Dengan demikian tujuan Anda adalah untuk meminimalkan lamanya hari kerja Anda dengan penjadwalan yang cerdas.

Fakta menyenangkan: ini adalah salah satu varian dari masalah penjadwalan birokrat yang malas , dan itu adalah NP-hard ( sumber ).

Memasukkan

Anda memiliki dua input: jumlah "unit waktu" di hari kerja Anda (bilangan bulat positif L), dan kumpulan tugas (array bilangan positif yang tidak kosong T, mewakili durasi tugas). Mereka dapat diambil dalam urutan apa pun, dan dalam format apa pun yang wajar. Array Tdapat berisi tugas dengan durasi lebih dari L, tetapi dijamin mengandung setidaknya satu tugas dengan durasi paling banyak L.

Keluaran

Sebuah jadwal yang berlaku adalah bagian dari tugas S ⊆ Tsehingga sum(S) ≤ L, dan setiap tugas tidak di S(penghitungan multiplicities) memiliki durasi ketat lebih dari L - sum(S). Output Anda akan menjadi jumlah terkecil dari jadwal yang valid. Dengan kata lain, Anda harus menampilkan jumlah minimal unit waktu yang harus Anda pakai hari ini.

Contoh

Pertimbangkan inputnya

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

Salah satu cara penjadwalan hari Anda adalah [4,4]: Anda menyelesaikan dua tugas dalam 8 unit waktu, dan memiliki 1 unit tersisa. Karena tidak ada tugas 1 unit yang tersedia, Anda dapat pulang. Namun, jadwalnya [2,5]bahkan lebih baik: Anda bekerja untuk 7 unit waktu, dan kemudian semua tugas yang tersisa akan membutuhkan 3 unit waktu atau lebih. Jadwal [2,4]tidak valid, karena setelah bekerja untuk 6 unit waktu, Anda masih punya cukup waktu untuk menyelesaikan tugas 3 unit. 7 unit ternyata menjadi optimal, sehingga output yang benar adalah 7.

Aturan dan penilaian

Anda dapat menulis program lengkap atau fungsi. Hitungan byte terendah menang, dan celah standar tidak diizinkan. Tidak ada batas waktu, jadi pemaksaan kasar dapat diterima dengan sempurna.

Uji kasus

Ini diberikan dalam format 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
Zgarb
sumber

Jawaban:

3

Jelly, 20 byte

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

Cobalah online!

TIO cukup cepat untuk menyelesaikan kasus uji terakhir dalam batas waktu 60 detik, bahkan jika hanya nyaris.

Latar Belakang

Algoritma ini sederhana dan tidak efisien:

  1. Kami menghasilkan semua himpunan bagian dari T , menghitung banyaknya.

  2. Kami memfilter himpunan bagian, hanya menjaga himpunan bagian tersebut yang memenuhi salah satu kriteria berikut:

    • S berbeda dari T , dan jumlah dari unsur-unsur S dan unsur minimal tidak di S lebih besar dari L .

    • S dan T identik.

    T yang difilter (sebut saja T ' ) sekarang berisi semua daftar tugas yang cukup bekerja (atau bahkan lembur).

  3. Dari semua S dalam T ' , pilih yang dengan jumlah terendah.

Bagaimana itu bekerja

Œ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.
Dennis
sumber
1

Pyth, 26 25 byte

JEhSsMf&gJsT>hS.-QT-JsTyQ

Cobalah online. Suite uji.

Saya belum bisa menjalankan dua test case terakhir (waktu mereka habis online, saya kira), tetapi semua yang lain berfungsi. Ini hanya solusi brute force dasar.

PurkkaKoodari
sumber
1

Ruby, 124 byte

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

Ini adalah solusi brute-force.

Tdk teratur
sumber
1

MATL , 36 byte

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

Cobalah 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
Luis Mendo
sumber