Picu peluncuran dan lindungi jackpot

23

Anda akan berpartisipasi dalam gameshow. Salah satu tantangannya adalah sebagai berikut:

  • Ruang pertama berisi sejumlah besar bola identik.
  • Ruang kedua berisi serangkaian peluncuran, masing-masing memiliki sensor yang menghitung berapa banyak bola telah ditempatkan di dalamnya. Sebuah bola yang ditempatkan di parasut tidak bisa dipulihkan.
  • Setiap peluncuran akan memicu setelah sejumlah bola (jumlah pemicu ) telah ditempatkan ke dalamnya. Saat dipicu, lampu berkedip, mengeluarkan suara, dan membuat Anda yakin bahwa itu telah memicu.
  • Anda harus memicu Npeluncuran untuk melanjutkan ke tantangan berikutnya.
  • Anda tahu pemicunya diperhitungkan, tetapi bukan korespondensi antara penghitungan dan peluncuran.
  • Anda memiliki satu kesempatan untuk mengambil bola dari ruang pertama ke ruang kedua. Setelah Anda memasukkan bola ke dalam parasut, Anda tidak bisa kembali untuk mendapatkan lebih banyak bola.
  • Setiap bola yang Anda ambil mengurangi uang dari jackpot.

Jelas Anda ingin memastikan bahwa Anda akan melewati tantangan, tetapi Anda ingin meminimalkan kehilangan uang jackpot. Tulis program, fungsi, kata kerja, dll. Untuk memberi tahu Anda berapa banyak bola yang Anda butuhkan.

Contoh

Misalkan jumlah pemicu adalah 2, 4, dan 10, dan Anda harus memicu 2 peluncuran untuk lulus. Ada strategi untuk mengoper dengan 10 bola: letakkan hingga 4 bola di luncuran pertama, hingga 4 bola di luncuran kedua, dan hingga 4 bola di luncuran ketiga. Karena salah satu dari tiga peluncuran akan memicu setelah hanya 2 bola, Anda hanya menggunakan total 10. Tidak ada strategi yang dijamin untuk bekerja dengan kurang dari 10, sehingga itu adalah hasil yang benar.

Memasukkan

Input terdiri dari array jumlah pemicu bilangan bulat dan bilangan bulat yang memberikan jumlah peluncuran untuk memicu. Anda dapat mengambil dua input dalam urutan mana pun, dan jika perlu Anda dapat mengambil input ketiga dengan panjang array.

Anda dapat mengasumsikan bahwa semua input lebih besar dari nol, dan bahwa jumlah peluncuran yang harus dipicu tidak melebihi jumlah peluncuran.

Anda juga dapat mengasumsikan bahwa jumlah diurutkan (naik atau turun), selama Anda menyatakan dengan jelas dalam jawaban Anda.

Keluaran

Outputnya harus berupa bilangan bulat tunggal, memberikan jumlah bola yang dibutuhkan oleh strategi optimal.

Uji kasus

Format: N counts solution

1 [2 4 10] 6
2 [2 4 10] 10
3 [2 4 10] 16
1 [3 5 5 5 5 5 5 5 5 5] 5
2 [1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 8 11] 8
2 [1 2 6 6 6 6 6 6 6 10] 16
2 [1 2 3 3 4 4 6 6 6 11] 17
3 [1 2 3 4 5 5 6] 16
3 [2 4 7 7 7 7 7 7 7] 21
5 [1 2 2 3 3 3 3 3 5 9 9 11] 27
2 [5 15 15] 25
1 [4 5 15] 10
3 [1 4 4 4] 10
2 [1 3 4] 6
2 [1 3 3 8] 8
Peter Taylor
sumber
Peringatan: jangan mencoba ninja!
Erik the Outgolfer
1
Bisakah Anda jelaskan mengapa test case terakhir memberi 10? Tidak bisakah satu tempat setidaknya 4 di masing-masing untuk memastikan setidaknya satu pemicu? Saya mungkin terlalu bodoh dan tidak membaca pertanyaan dengan cukup baik, tetapi saya tidak mengerti.
Tn. Xcoder
2
@Rod Anda hanya perlu menempatkan 5 di dua dari mereka sebelum satu dijamin dipicu, 5 * 2 = 10
H.PWiz
3
@ H.PWiz Terima kasih, sekarang mengerti. Tantangannya tampaknya jauh lebih rumit sekarang ....
Tn. Xcoder
1
@ Mr.Xcoder, ya, tetapi Anda harus yakin berhasil dalam kasus terburuk.
Peter Taylor

Jawaban:

4

Python, 222 198 byte

def S(G,P,T=0):
 T=T or[0]*len(P);r=[0]*(sum(t>=p for t,p in zip(T,P))>=G)
 for i,t in enumerate(T):
    if t<max(P):a=next(p for p in P if p>t)-t;T[i]+=a;r+=[a+S(G,P,sorted(T))];T[i]-=a
 return min(r)

Penggunaan adalah S(2, (2, 4, 10)).

Untuk menguji program ini pada kecepatan yang layak, tambahkan memoisasi dengan meletakkannya setelah definisi fungsi:

old_s = S
mem = {}
def S(G, P, T=0):
    k = (G, tuple(P), T and tuple(T) or 0)
    if k in mem: return mem[k]
    r = old_s(G, P, T)
    mem[k] = r
    return r

Kami melakukan pemrograman dinamis pada array T yang berisi jumlah bola yang kami lemparkan ke setiap saluran, awalnya semua nol. Tanpa memberikan bukti yang kuat, saya mengklaim bahwa kita dapat menjaga T diurutkan setiap saat, yaitu, asumsikan kita selalu melempar bola paling banyak ke dalam peluncuran terakhir, yang pada gilirannya kita akan anggap sebagai peluncuran terbesar.

Jika kemudian T, ketika elemen yang cocok untuk elemen dengan P (yang merupakan input masalah kami), memiliki setidaknya elemen G (yang merupakan tujuan kami) lebih besar, kami telah menemukan solusi, dan kami mengembalikan 0, karena kami harus melempar 0 lebih banyak bola untuk menemukan solusi. Ini berarti bahwa jika G adalah 1, luncuran kami yang paling sedikit harus mengandung jumlah bola yang sama atau lebih banyak daripada persyaratan luncuran terkecil, dan seterusnya untuk G. yang lebih besar.

Kalau tidak, untuk setiap posisi kita melempar bola yang cukup untuk meningkatkan ke persyaratan peluncuran berikutnya (apa pun di antaranya tidak akan pernah bisa diamati) dan muncul kembali. Kami kemudian mengembalikan minimum panggilan rekursif ini.

orlp
sumber
215 byte dengan menghapus continue.
Tn. Xcoder
1
195 byte dengan menghapusenumerate
Felipe Nardi Batista
4

Haskell, 124 117 100 98 91 80 78 byte

Disimpan 11 byte berkat @Peter Taylor

0#_=0
n#a=minimum$zipWith(\x y->x*y+(n-1)#(snd.splitAt y$a))a[1..length a-n+1]

Cobalah online!

(#) mengambil bilangan bulat dan daftar bilangan bulat dalam urutan menurun sebagai argumen

Penggunaan adalah 1#[10,4,2]

Penjelasan:

Untuk setiap nilai, x, di posisi i (1-idexed) dalam daftar, taktik terbaik untuk menghapus elemen itu (atau sejumlah elemen yang kurang dari atau sama dengan x) adalah menuangkan bola x ke dalam peluncuran.

Untuk setiap elemen, x, pada posisi i dalam daftar, (n #) menghitung x * i + ((n-1) #) dari daftar di luar posisi i (hingga n adalah 0). Maka dibutuhkan minimum dari semua kemungkinan yang diperiksa.

H.Piz
sumber
3

Haskell , 54 byte

(%)0
(p%l)n|h:t<-l=p+min(p%t$n)(h%t$n-1)|n<1=p|1>0=1/0

Cobalah online!

Mengambil daftar dalam urutan menaik.

Tidak
sumber
Catatan untuk diri sendiri: lain kali bersikeras bahwa output harus tipe integer.
Peter Taylor
1
Saya tidak tahu cukup Haskell untuk mencari tahu ini, bisakah Anda menambahkan penjelasan?
orlp
2

Python, 73 byte

f=lambda n,c:n and min(c[i]*-~i+f(n-1,c[-~i:])for i in range(len(c)-n+1))

Port jawaban H.PWiz's Haskell. Membutuhkan input dalam urutan menurun.

orlp
sumber
1

CJam (35 byte)

{:A,,e!f<{$__(;A,+.-\Af=.*1bz}%:e<}

Demo online

Mengambil input sebagai N counts asumsi yang countsdisortir dalam urutan menaik.

Pembedahan

Nyatakan jumlah dalam urutan menurun sebagai array 1-diindeks C(jadi elemen kedua Cadalah jumlah terbesar kedua). Misalkan kita akhirnya menang dengan memicu peluncuran C[a_0], C[a_1], ... C[a_{N-1}]. Kemudian dalam kasus terburuk, untuk setiap C[a_i]kami telah menempatkan setidaknya C[a_i]bola ke masing-masing chutes 1untuk a_i. Jadi kami menempatkan C[a_{N-1}]bola ke a_{N-1}peluncuran, C[a_{N-2}]bola tambahan ke dalama_{N-2} dalamnya, ...

Lebih dari setiap himpunan bagian N, yang memberi kita jumlah terkecil? Maka kita harus berusaha untuk menang dengan himpunan bagian itu.

NB Kode sebenarnya menggunakan jumlah dalam urutan menaik, tapi saya pikir urutan menurun lebih intuitif.

{         e# Define a block
  :A      e#   Store the sorted counts as A
  ,,e!f<  e#   Get all N-element subsets of A's indices
  {       e#   Map over these subsets S:
    $__   e#     Sort the subset and get a couple of copies
    (;A,+ e#     Remove the first element from one copy and append len(A)
    .-    e#     Pointwise subtraction, giving [S[0]-S[1] S[1]-S[2] ...]
    \Af=  e#     Get the counts [A[S[0]] A[S[1]] ...]
    .*    e#     Pointwise multiplication
    1bz   e#     Sum and take absolute value, giving the worst case score
  }%
  :e<     e#   Select the minimum worst case score
}
Peter Taylor
sumber