Masz n
monety, z których każda waży -1 lub 1. Każda jest oznaczona od 0
do, n-1
dzięki czemu możesz rozróżnić monety. Masz także jedno (magiczne) urządzenie do ważenia. Za pierwszym razem możesz włożyć tyle monet, ile chcesz w urządzenie ważące, które jest w stanie zmierzyć zarówno masy ujemne, jak i dodatnie, i dokładnie powie, ile ważą.
Jednak w urządzeniu ważącym jest coś naprawdę dziwnego. Jeśli x_1, x_2, ..., x_j
po raz pierwszy umieścisz monety w urządzeniu, następnym razem będziesz musiał umieścić monety (x_1+1), (x_2+1) , ..., (x_j+1)
na skali, z tym wyjątkiem, że oczywiście nie możesz włożyć monet o numerze wyższym niż n-1
. Co więcej, przy każdym nowym ważeniu możesz wybrać, czy chcesz umieścić monetę 0
na wadze .
Zgodnie z tą zasadą, jaka jest najmniejsza liczba ważeń, które zawsze powiedzą dokładnie, które monety ważą 1, a które -1?
Oczywiście można po prostu położyć monetę 0
na urządzeniu w pierwszym zakręcie, a następnie zajmie to dokładne n
ważenie, aby rozwiązać problem.
Języki i biblioteki
Możesz użyć dowolnego języka lub biblioteki, która Ci się podoba (która nie została zaprojektowana do tego wyzwania). Chciałbym jednak móc przetestować Twój kod, jeśli to możliwe, więc jeśli możesz podać jasne instrukcje dotyczące uruchamiania go w Ubuntu, byłoby to bardzo mile widziane.
Wynik
Dla danego n
wyniku twój wynik jest n
dzielony przez liczbę ważeń, których potrzebujesz w najgorszym przypadku. Wyższe wyniki są zatem lepsze. Ta układanka nie ma wkładu, ale Twoim celem jest znalezienie takiej, n
dla której możesz uzyskać najwyższy wynik.
Jeśli jest remis, pierwsza odpowiedź wygrywa. W niezwykle mało prawdopodobnej sytuacji, gdy ktoś znajdzie sposób na uzyskanie nieskończonej liczby punktów, ta osoba wygrywa natychmiast.
Zadanie
Twoim zadaniem jest po prostu napisanie kodu, który uzyska najwyższy wynik. Twój kod będzie musiał zarówno wybrać n sprytnie, a następnie zoptymalizować liczbę ważeń n
.
Wiodące wpisy
4/37/5 w Pythonie Sarge Borsch- 26/14 na Jawie autorstwa Petera Taylora
źródło
x_i
: Możemy na przykład wykonać pierwsze ważenie (x_1, x_2, x_3) = (3, 2, 7), a następnie drugie ważenie może mieć wartość (4, 3, 8) lub ( 0, 4, 3, 8). Etykiety monet nie muszą być następujące po sobie, a indeksi
wx_i
nie odnosi się do etykiety monety.Odpowiedzi:
C ++, wynik
23/1225/1327/1428/14 = 231/15Ponownie sprawdzone rozwiązania właściwości Matrix X (lub Radość X) są bezpośrednio użyteczne jako rozwiązania tego problemu. Np. Rozwiązanie 31 rzędów 15 kolumn:
wiersz N reprezentuje monety, które umieściłeś na wadze do pomiaru N. Bez względu na uzyskane wyniki ważenia, oczywiście istnieje pewien zestaw wartości monet, które dają tę wagę. Jeśli istnieje także inna kombinacja (rozwiązanie nie jest unikalne), zastanów się, jak się różnią. Zestaw monet należy zastąpić ważeniem
1
monet-1
. Daje to zestaw kolumn odpowiadających temu odwróceniu. Istnieje również zestaw wag-1
, które zastępujesz1
. To kolejny zestaw kolumn. Ponieważ pomiary nie zmieniają się między dwoma rozwiązaniami, oznacza to, że sumy kolumn dwóch zbiorów muszą być takie same. Ale ponownie sprawdzono rozwiązania właściwości Matrix X (lub Radość X) są dokładnie tymi macierzami, w których takie zestawy kolumn nie istnieją, więc nie ma duplikatów, a każde rozwiązanie jest unikalne.Każdy rzeczywisty zestaw pomiarów można opisać za pomocą jakiejś
0/1
macierzy. Ale nawet jeśli niektóre zestawy kolumn sumują się z tymi samymi wektorami, może się zdarzyć, że znaki wartości monet rozwiązania kandydującego nie odpowiadają dokładnie takiemu zestawowi. Nie wiem więc, czy macierze takie jak powyższa są optymalne. Ale przynajmniej zapewniają dolną granicę. Zatem możliwość wykonania 31 monet w mniej niż 15 pomiarach jest nadal otwarta.Zauważ, że jest to prawdą tylko w przypadku nieokreślonej strategii, w której decyzja o umieszczeniu monety
0
na wadze zależy od wyniku poprzednich ważeń. W przeciwnym razie będziemy mieć rozwiązania, gdzie znaki monet odpowiadają zestawów, które mają taką samą sumę kolumny.źródło
Python 2, wynik = 1,0
To łatwy wynik, na wypadek, gdyby nikt nie znalazł lepszego wyniku (wątpliwe).
n
ważenia dla każdegon
.Zaimportowałem,
antigravity
aby program mógł pracować z ujemnymi wagami.źródło
antigravity
to w zasadzie brak operacji, prawda?Wynik = 26/14 ~ = 1,857
Zapisz jako
LembikWeighingOptimisation.java
, skompiluj jakojavac LembikWeighingOptimisation.java
, uruchom jakojava LembikWeighingOptimisation
.Ogromne podziękowania dla Mitcha Schwartza za wskazanie błędu w pierwszej wersji szybkiego odrzucania.
Wykorzystuje to kilka dość podstawowych technik, których nie mogę dokładnie uzasadnić. To brutalne siły, ale tylko do rozpoczęcia operacji ważenia, które używają co najwyżej połowy monet: sekwencji, które wykorzystują więcej niż połowę monet, nie można bezpośrednio przenieść na uzupełniające ważenia (ponieważ nie znamy masy całkowitej), ale na falistym poziomie powinno być około tyle samo informacji. Powtarza również od początku ważenia w kolejności od liczby zaangażowanych monet, na tej podstawie, że w ten sposób obejmuje ważenia rozproszone (które, mam nadzieję, stosunkowo wcześnie podają informacje o górnej części), bez uprzedniego przeszukiwania wiązki, która zaczyna się gęstym podzbiorem dolny koniec.
MaskRange
Klasa jest ogromny postęp w stosunku do wcześniejszych wersji pod względem zużycia pamięci i usuwa z GC jest wąskim gardłem.źródło
Python 3,
wynik = 4/3 = 1,33… (N = 4)wynik = 1,4 (N = 7)Aktualizacja: zaimplementowano wyszukiwanie siłowe w zestawie „statycznych” solverów i otrzymano nowy wynik
Myślę, że można go jeszcze ulepszyć, szukając dynamicznych solverów, które mogą wykorzystywać wyniki ważenia do dalszych decyzji.
Oto kod Pythona, który przeszukuje wszystkie statyczne solwery w poszukiwaniu małych
n
wartości (te solwery zawsze ważą te same zestawy monet, stąd nazwa „statyczna”) i określa ich najgorszy przypadek liczby kroków po prostu sprawdzając, czy ich wyniki pomiaru pozwalają tylko na jedną pasującą monetę ustawione we wszystkich przypadkach. Ponadto śledzi najlepszy wynik znaleziony do tej pory i wczesne narzędzia do usuwania śliwek, które wykazały, że są zdecydowanie gorsze niż te, które znaleziono wcześniej. To była ważna optymalizacja, w przeciwnym razie nie mógłbym czekać na ten wynik zn
= 7. (Ale najwyraźniej nadal nie jest zbyt dobrze zoptymalizowany)Zadaj pytanie, jeśli nie jest jasne, jak to działa…
Wyjście:
Ta linia
(StaticSolver({0,2}, {0,1,3}, {0,1,2,4}, {1,2,3,5}, {0,2,3,4,6}), 5), score = 7/5 = 1.4
odkrywa najlepszy znaleziony solver. Liczby w{}
nawiasach to wskaźniki monet, które należy umieścić na urządzeniu ważącym na każdym kroku.źródło