Kích hoạt máng và bảo vệ giải độc đắc


23

Bạn sẽ tham gia vào một gameshow. Một trong những thách thức hoạt động như sau:

  • Phòng đầu tiên chứa một số lượng lớn các quả bóng giống hệt nhau.
  • Phòng thứ hai chứa một loạt các máng, mỗi máng có một cảm biến để đếm xem có bao nhiêu quả bóng được đặt trong đó. Một quả bóng được đặt trong máng không thể lấy lại được.
  • Mỗi máng sẽ kích hoạt sau khi một số lượng bóng nhất định ( số lần kích hoạt của nó ) đã được đặt vào nó. Khi nó kích hoạt, nó sẽ nháy đèn, tạo ra tiếng ồn và khiến bạn không nghi ngờ gì rằng nó đã được kích hoạt.
  • Bạn phải kích hoạt Nmáng để tiếp tục thử thách tiếp theo.
  • Bạn biết số lần kích hoạt, nhưng không phải là sự tương ứng giữa đếm và máng.
  • Bạn có một cơ hội để đưa bóng từ phòng thứ nhất vào phòng thứ hai. Một khi bạn đặt một quả bóng vào máng, bạn không thể quay lại để lấy thêm bóng.
  • Mỗi quả bóng mà bạn lấy tiền từ giải độc đắc.

Rõ ràng bạn muốn đảm bảo rằng bạn sẽ vượt qua thử thách, nhưng bạn muốn giảm thiểu việc mất tiền jackpot. Viết chương trình, chức năng, động từ, v.v. để cho bạn biết bạn cần bao nhiêu quả bóng.

Thí dụ

Giả sử số lượng kích hoạt là 2, 4 và 10, và bạn cần kích hoạt 2 máng để vượt qua. Có một chiến lược để vượt qua với 10 quả bóng: đặt tối đa 4 quả bóng trong máng thứ nhất, tối đa 4 quả bóng trong máng thứ hai và tối đa 4 quả bóng trong máng thứ ba. Vì một trong ba máng sẽ kích hoạt chỉ sau 2 quả bóng, bạn chỉ sử dụng tổng cộng 10. Không có chiến lược nào được đảm bảo hoạt động với ít hơn 10, vì vậy đó là đầu ra chính xác.

Đầu vào

Đầu vào bao gồm một mảng số lượng kích hoạt số nguyên và một số nguyên cho số lượng máng để kích hoạt. Bạn có thể lấy hai đầu vào theo thứ tự, và nếu cần, bạn có thể lấy đầu vào thứ ba với độ dài của mảng.

Bạn có thể giả định rằng tất cả các đầu vào đều lớn hơn 0 và số lượng các máng phải được kích hoạt không vượt quá số lượng các máng.

Bạn cũng có thể giả định rằng số đếm được sắp xếp (tăng dần hoặc giảm dần), miễn là bạn nêu rõ điều đó trong câu trả lời của mình.

Đầu ra

Đầu ra phải là một số nguyên duy nhất, đưa ra số lượng bóng theo yêu cầu của chiến lược tối ưu.

Các trường hợp thử nghiệm

Định dạng: 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

Cảnh báo: đừng cố gắng ninja!
Erik the Outgolfer

1
Bạn có thể vui lòng giải thích tại sao trường hợp thử nghiệm cuối cùng cho 10? Không nên đặt ít nhất 4 vị trí trong mỗi vị trí để đảm bảo ít nhất một kích hoạt? Tôi có lẽ quá ngu ngốc và đã không đọc câu hỏi đủ tốt, nhưng tôi không hiểu nó.
Ông Xcoder

2
@Rod Bạn chỉ cần đặt 5 trong hai trong số chúng trước khi một được đảm bảo kích hoạt, 5 * 2 = 10
H.PWiz

3
@ H.PWiz Cảm ơn, giờ đã hiểu. Thử thách dường như phức tạp hơn nhiều bây giờ ....
Ông Xcoder

1
@ Mr.Xcoder, vâng, nhưng bạn phải chắc chắn thành công trong trường hợp xấu nhất.
Peter Taylor

Câu trả lời:


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)

Cách sử dụng là S(2, (2, 4, 10)).

Để kiểm tra chương trình này ở bất kỳ tốc độ tốt nào, hãy thêm ghi nhớ bằng cách đặt chương trình này sau định nghĩa hàm:

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

Chúng tôi lập trình động trên một mảng T có chứa số lượng bóng chúng tôi ném vào mỗi máng, ban đầu là tất cả các số không. Không đưa ra một bằng chứng nghiêm ngặt, tôi khẳng định rằng chúng ta có thể giữ T được sắp xếp mọi lúc, nghĩa là chúng ta luôn ném nhiều quả bóng nhất vào máng cuối, do đó chúng ta sẽ cho rằng đó là máng lớn nhất.

Nếu sau đó T, khi phần tử khớp với phần tử với P (là đầu vào vấn đề của chúng tôi), có ít nhất các phần tử G (là mục tiêu của chúng tôi) lớn hơn, chúng tôi đã tìm thấy giải pháp và chúng tôi trả về 0, vì chúng tôi cần ném 0 nhiều bóng hơn để tìm một giải pháp. Điều này có nghĩa là nếu G là 1, máng ném ít nhất của chúng ta phải chứa một lượng bóng bằng hoặc nhiều hơn so với yêu cầu máng nhỏ nhất, v.v.

Mặt khác, đối với mỗi vị trí, chúng tôi ném vào các quả bóng đủ để nâng cấp lên yêu cầu máng tiếp theo (mọi thứ ở giữa sẽ không bao giờ có thể quan sát được) và tái diễn. Sau đó chúng tôi trả lại mức tối thiểu của các cuộc gọi đệ quy này.


215 byte bằng cách loại bỏ continue.
Ông Xcoder

1
195 byte bằng cách xóaenumerate
Felipe Nardi Batista

4

Haskell, 124 117 100 98 91 80 78 byte

Đã lưu 11 byte nhờ @Peter Taylor

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

Hãy thử trực tuyến!

(#) lấy một số nguyên và một danh sách các số nguyên theo thứ tự giảm dần làm đối số

Cách sử dụng là 1#[10,4,2]

Giải thích:

Đối với mỗi giá trị, x, ở vị trí i (1 idexed) trong danh sách, chiến thuật tốt nhất để loại bỏ phần tử đó (hoặc một số lượng phần tử nhỏ hơn hoặc bằng x) là đổ x bi vào i máng.

Đối với mỗi phần tử, x, ở vị trí i trong danh sách, (n #) sẽ tính x * i + ((n-1) #) của danh sách ngoài vị trí i (cho đến khi n bằng 0). Sau đó, nó mất tối thiểu của tất cả các khả năng được kiểm tra.


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

Hãy thử trực tuyến!

Đưa danh sách theo thứ tự tăng dần.


Lưu ý đến bản thân: lần sau nhấn mạnh rằng đầu ra phải là một kiểu số nguyên.
Peter Taylor

1
Tôi không biết đủ Haskell để tìm ra điều này, bạn có thể thêm một lời giải thích?
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))

Cổng câu trả lời Haskell của H.PWiz. Yêu cầu đầu vào phải theo thứ tự giảm dần.


1

CJam (35 byte)

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

Bản demo trực tuyến

Đưa đầu vào như N countsgiả sử countsđược sắp xếp theo thứ tự tăng dần.

Mổ xẻ

Biểu thị số đếm theo thứ tự giảm dần dưới dạng mảng 1 chỉ mục C(vì vậy phần tử thứ hai củaC là số lớn thứ hai). Giả sử rằng chúng ta kết thúc chiến thắng bằng cách kích hoạt các máng trượt C[a_0], C[a_1], ... C[a_{N-1}]. Sau đó, trong trường hợp xấu nhất, với mỗi C[a_i]chúng ta đã đặt ít nhất các C[a_i]quả bóng vào mỗi máng 1để a_i. Vì vậy, chúng tôi đặt C[a_{N-1}]quả bóng vào a_{N-1}máng, một C[a_{N-2}]quả bóng bổ sung vào a_{N-2}chúng, ...

Trên mỗi tập hợp con của Nsố đếm, số nào cho chúng ta tổng nhỏ nhất? Sau đó, chúng ta nên đặt mục tiêu giành chiến thắng với tập hợp con số đó.

NB Mã thực sự sử dụng số đếm theo thứ tự tăng dần, nhưng tôi nghĩ thứ tự giảm dần là trực quan hơn.

{         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
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.