Ostatnio w Puzzling.SE napotkałem problem związany z określeniem, które dwie butelki z większej liczby są zatrute, gdy trucizna aktywuje się tylko wtedy, gdy oba składniki są pijane. Skończyło się to dość ciężką próbą, a większość ludzi zdołała sprowadzić go do 18 lub 19 więźniów przy użyciu zupełnie innych algorytmów.
Oryginalna deklaracja problemu jest następująca:
Jesteś władcą średniowiecznego królestwa, który uwielbia organizować przyjęcia. Dworzanin, który ostatni raz próbował otruć jedną z twoich butelek wina, był wściekły, gdy dowiedział się, że udało ci się zidentyfikować, którą butelkę zatruł na 1000 z zaledwie dziesięcioma więźniami.
Tym razem jest trochę bardziej sprytny. Opracował złożoną truciznę
P
: podwójny płyn, który jest śmiertelny tylko wtedy, gdy zmieszają się dwa indywidualnie nieszkodliwe składniki; jest to podobne do działania żywicy epoksydowej. Wysłał ci kolejną skrzynię 1000 butelek wina. Jedna butelka ma składnik,C_a
a druga ma składnikC_b
. (P = C_a + C_b
)Każdy, kto pije oba składniki, umrze po północy w noc, w której wypił ostatni składnik, niezależnie od tego, kiedy w ciągu dnia wchłonął płyn. Każdy składnik trucizny pozostaje w ciele, dopóki drugi składnik nie zostanie aktywowany, więc jeśli wypijesz jeden składnik jednego dnia, a drugi następnego, umrzesz o północy pod koniec drugiego dnia.
Masz dwa dni do następnej imprezy. Jaka jest minimalna liczba więźniów, których należy użyć do testowania, aby zidentyfikować, które dwie butelki są skażone, i jakiego algorytmu należy przestrzegać przy tej liczbie więźniów?
Premia
Dodatkowo, przypuśćmy, że dysponowałeś stałym limitem 20 więźniów, jaka jest maksymalna liczba butelek, które możesz teoretycznie przetestować i dojść do dokładnego wniosku, na które butelki miało to wpływ?
Twoim zadaniem jest zbudowanie programu do rozwiązania problemu bonusowego. Biorąc pod uwagę n
więźniów, twój program opracuje harmonogram testów, który będzie w stanie wykryć dwie zatrute butelki wśród m
butelek, gdzie m
są one tak duże, jak to możliwe.
Twój program początkowo przyjmie jako dane wejściowe liczbę N
, liczbę więźniów. Następnie wyświetli:
M
, liczba butelek, które spróbujesz przetestować. Te butelki będą oznaczone od1
doM
.N
linie zawierające etykiety butelek, które wypije każdy więzień.
Twój program pobierze następnie dane wejściowe, którzy więźniowie zmarli pierwszego dnia, z więźniem w pierwszej linii 1
, w kolejnej linii 2
itd. Następnie wyświetli:
N
więcej linii, zawierających etykiety butelek, które każdy więzień wypije. Martwi więźniowie będą mieli puste linie.
Twój program następnie weźmie pod uwagę, którzy więźniowie zmarli drugiego dnia, i wyśle dwie liczby, A
i B
reprezentując, które dwie butelki twój program uważa za truciznę.
Przykładem wejście dla dwóch więźniów i cztery butelki może iść jako takie, czy butelek 1
i 3
są zatrute:
> 2 // INPUT: 2 prisoners
4 // OUTPUT: 4 bottles
1 2 3 // OUTPUT: prisoner 1 will drink 1, 2, 3
1 4 // OUTPUT: prisoner 2 will drink 1, 4
> 1 // INPUT: only the first prisoner died
// OUTPUT: prisoner 1 is dead, he can't drink any more bottles
3 // OUTPUT: prisoner 2 drinks bottle 3
> 2 // INPUT: prisoner 2 died
1 3 // OUTPUT: therefore, the poisoned bottles are 1 and 3.
The above algorithm may not actually work in all
cases; it's just an example of input and output.
Harmonogram testów Twojego programu musi z powodzeniem określać każdą możliwą parę zatrutych butelek, aby mogła być ważna.
Twój program będzie oceniany według następujących kryteriów, w kolejności:
Maksymalna liczba butelek, jaką może rozpoznać dla skrzynki
N = 20
.Liczba butelek w skrzynce
N = 21
, a następnie kolejne skrzynie.Długość kodu. (Wygrywa krótszy kod).