Dla danej dodatniej liczby całkowitej n
należy uwzględnić wszystkie ciągi binarne długości 2n-1
. Dla danego łańcucha S
, niech L
będzie tablica długości n
, który zawiera licznik liczby 1
sekund w każdym z fragmentu o długości n
od S
. Na przykład, jeśli n=3
i S = 01010
wtedy L=[1,2,1]
. Nazywamy L
tablicę zliczającą S
.
Mówimy, że dwa ciągi S1
i S2
tej samej długości meczu jeśli ich odpowiednie tablice liczenia L1
i L2
mają tę właściwość, że L1[i] <= 2*L2[i]
i L2[i] <= 2*L1[i]
dla wszystkich i
.
Zadanie
Aby zwiększyć, n
zaczynając od n=1
, zadaniem jest znalezienie rozmiaru największego zestawu ciągów, z których każdy ma długość, 2n-1
tak aby żadne dwa ciągi nie pasowały.
Twój kod powinien wypisywać jedną liczbę na wartość n
.
Wynik
Twój wynik jest najwyższy, n
dla którego nikt inny nie opublikował wyższej poprawnej odpowiedzi na którąkolwiek z twoich odpowiedzi. Oczywiście, jeśli masz wszystkie optymalne odpowiedzi, otrzymasz wynik za najwyższą, n
którą opublikujesz. Jednak nawet jeśli twoja odpowiedź nie jest optymalna, nadal możesz uzyskać wynik, jeśli nikt inny go nie pokona.
Przykładowe odpowiedzi
Bo n=1,2,3,4
dostaję 2,4,10,16
.
Języki i biblioteki
Możesz użyć dowolnego dostępnego języka i bibliotek, które ci się podobają. Tam, gdzie to możliwe, dobrze byłoby móc uruchomić kod, więc proszę podać pełne wyjaśnienie, w jaki sposób uruchomić / skompilować kod w systemie Linux, jeśli to w ogóle możliwe.
Wiodące wpisy
- 5 autorstwa Martina Büttnera w Mathematica
- 6 autorstwa Reto Koradi w C ++ . Wartości są
2, 4, 10, 16, 31, 47, 75, 111, 164, 232, 328, 445, 606, 814, 1086
. Pierwsze 5 jest znanych jako optymalne. - 7 autorstwa Petera Taylora w Javie . Wartości są
2, 4, 10, 16, 31, 47, 76, 111, 166, 235
. - 9 autorstwa joriki w Javie . Wartości są
2, 4, 10, 16, 31, 47, 76, 112, 168
.
L1[i]/2 <= L2[i] <= 2*L1[i]
.match(A, B)
imatch(B, C)
nie oznaczamatch(A, C)
(to samo dla odwrotności). Przykład: dopasowanie [1] i [2], dopasowanie [2] i [3], ale [1] i [3] nie. Podobnie, [1,3] i [3,1] nie pasują, [3, 1] i [2, 3] nie pasują, ale [1, 3] i [2, 3] pasują.Odpowiedzi:
2, 4, 10, 16, 31, 47, 76, 112, 168
Dla każdego n ten kod Java określa możliwe tablice zliczające, a następnie znajduje niepasujące zestawy o rosnącym rozmiarze, dla każdego rozmiaru rozpoczynającego się od zestawu losowego i ulepszającego go przez losowe najbardziej strome zejście. Na każdym etapie jeden z elementów zestawu jest losowo wybierany równomiernie i zastępowany przez inny układ liczący losowo wybierany losowo spośród nieużywanych. Krok zostanie zaakceptowany, jeśli nie zwiększy liczby dopasowań. Ta ostatnia recepta wydaje się być kluczowa; akceptowanie kroków tylko wtedy, gdy zmniejszają liczbę dopasowań, nie jest tak skuteczne. Kroki pozostawiające niezmienną liczbę dopasowań pozwalają na zbadanie przestrzeni wyszukiwania, a ostatecznie może zostać otwarta przestrzeń, aby uniknąć jednego z dopasowań. Po 2 ^ 24 krokach bez poprawy poprzedni rozmiar jest wyprowadzany dla bieżącej wartości n, a n jest zwiększany.
Wyniki do n = 9 są
2, 4, 10, 16, 31, 47, 76, 112, 168
lepsze od poprzednich wyników dla n = 8 o jeden i dla n = 9 o dwa. W przypadku wyższych wartości n może być konieczne zwiększenie limitu 2 ^ 24 kroków.Próbowałem również symulować wyżarzanie (z liczbą dopasowań jako energią), ale bez poprawy w porównaniu z najbardziej stromym spadkiem.
Kod
zapisz jako
Question54354.java
kompiluj z
javac Question54354.java
uruchom z
java Question54354
źródło
2, 4, 10, 16, 31, 47, 76, 111, 166, 235
Notatki
Jeśli weźmiemy pod uwagę wykres
G
z wierzchołkami0
don
i krawędziami łączącymi dwie pasujące liczby, to siła tensoraG^n
ma wierzchołki(x_0, ..., x_{n-1})
tworzące siłę kartezjańską{0, ..., n}^n
i krawędzie między pasującymi krotkami. Wykres zainteresowania to podrozdziałG^n
indukowany przez te wierzchołki, które odpowiadają możliwym „macierzom zliczającym”.Zatem pierwszym podzadaniem jest wygenerowanie tych wierzchołków. Naiwne podejście wylicza ponad
2^{2n-1}
łańcuchami lub według kolejności4^n
. Jeśli jednak spojrzymy na tablicę pierwszych różnic tablic liczących, stwierdzimy, że są tylko3^n
możliwości, a na podstawie pierwszych różnic możemy wydedukować zakres możliwych wartości początkowych, wymagając, aby żaden element w zerowych różnicach nie był mniejszy niż0
lub większy niżn
.Następnie chcemy znaleźć maksymalny niezależny zestaw. Używam jednego twierdzenia i dwóch heurystyk:
(n, n, ..., n)
będzie to maksymalnie niezależny zestaw. Jest dość duża klika wierzchołków,{m, m+1, ..., n}^n
gdziem
jest najmniejszą liczbą całkowitą, która pasujen
;(n, n, ..., n)
gwarantuje, że nie będzie pasować poza tą kliką.Na moim komputerze jest to wykrywane
111
przezn=8
16 sekund,166
przezn=9
około 8 minut i235
przezn=10
około 2 godziny.Kod
Zapisz jako
PPCG54354.java
, skompiluj jakojavac PPCG54354.java
i uruchom jakojava PPCG54354
.źródło
Mathematica
n = 5
,, 31 strunWłaśnie napisałem rozwiązanie brutalnej siły przy użyciu wbudowanych aplikacji Mathematica, aby zweryfikować przykładowe odpowiedzi Lembika, ale może ono również obsłużyć
n = 5
:Jako bonus, ten kod tworzy wizualizację problemu w postaci wykresu, na którym każda krawędź wskazuje dwa pasujące ciągi.
Oto wykres dla
n = 3
:źródło
C ++ (heurystyczny): 2, 4, 10, 16, 31, 47, 75, 111, 164, 232, 328, 445, 606, 814, 1086
Jest to nieco poniżej wyniku Petera Taylora, będąc o 1 do 3 niższym dla
n=7
,9
i10
. Zaletą jest to, że jest znacznie szybszy, więc mogę uruchomić go dla wyższych wartościn
. I można to zrozumieć bez jakiejkolwiek fantazyjnej matematyki. ;)Bieżący kod jest zwymiarowany do uruchomienia
n=15
. Czasy pracy zwiększają się z grubsza o współczynnik 4 dla każdego wzrostu wn
. Na przykład było to 0,008 sekundy dlan=7
, 0,07 sekundy dlan=9
, 1,34 sekundy dlan=11
, 27 sekund dlan=13
i 9 minut dlan=15
.Użyłem dwóch kluczowych obserwacji:
c
z wyłączeniem zakresc / 2
do2 * c
innych wartości. W przypadku mniejszych wartościc
ten zakres jest mniejszy, co oznacza, że przy jego użyciu wykluczonych jest mniej wartości.Generuj unikalne tablice liczące
Wykorzystałem tę brutalną siłę, iterując wszystkie wartości, generując tablicę zliczeń dla każdej z nich i ujednolicając wynikową listę. Z pewnością można to zrobić bardziej efektywnie, ale jest wystarczająco dobre dla rodzajów wartości, z którymi operujemy.
Jest to niezwykle szybkie w przypadku małych wartości. W przypadku większych wartości narzut staje się znaczny. Na przykład
n=15
używa około 75% całego środowiska wykonawczego. To zdecydowanie byłby obszar, na który należy zwrócić uwagę, gdy próbuje się wznieść znacznie wyżejn=15
. Problemem może stać się nawet użycie pamięci do budowania listy tablic zliczających dla wszystkich wartości.Liczba unikalnych tablic zliczających wynosi około 6% liczby wartości
n=15
. Ta względna liczba maleje wraz zen
wzrostem.Chciwy wybór wartości tablicy zliczającej
Główna część algorytmu wybiera zliczanie wartości tablic z wygenerowanej listy, stosując proste podejście zachłanne.
W oparciu o teorię, że korzystanie z tablic zliczających z małą liczbą jest korzystne, tablice zliczające są sortowane według sumy ich zliczeń.
Są one następnie sprawdzane w kolejności i wybierana jest wartość, jeśli jest zgodna ze wszystkimi poprzednio używanymi wartościami. Oznacza to jedno pojedyncze przejście liniowe przez unikalne tablice zliczające, w których każdy kandydat jest porównywany z wcześniej wybranymi wartościami.
Mam kilka pomysłów, w jaki sposób heurystykę można potencjalnie poprawić. Wydawało się to jednak rozsądnym punktem wyjścia, a wyniki wyglądały całkiem dobrze.
Kod
To nie jest wysoce zoptymalizowane. W pewnym momencie miałem bardziej rozbudowaną strukturę danych, ale potrzebowałem więcej pracy, aby ją uogólnić
n=8
, a różnica w wydajności nie wydawała się bardzo znacząca.źródło
n=4
już trochę czasu . To mogło się skończyćn=5
z pewną cierpliwością. Musiałeś użyć lepszej strategii cofania się, aby to zrobićn=7
. Czy Twoja była heurystyczna, czy też badała całą przestrzeń rozwiązań? Zastanawiam się nad pomysłami, jak to poprawić, albo poprzez dostrojenie porządku sortowania, albo może nie będąc całkowicie chciwym.3^n
i dwie heurystyki, które opisuje.n=7
szybko znajduje 76 . Ale próbując tegon=9
, nadal utknąłem na 164, kiedy zatrzymałem go po 20 minutach. Tak więc rozszerzenie tej formy o ograniczoną formę prostego cofania nie wydaje się ogólnie obiecujące.