tło
Rozważ (zamknięty) łańcuch prętów, z których każdy ma całkowitą długość. Ile odrębnych polominoów bez dziur można utworzyć za pomocą danego łańcucha? Innymi słowy, ile różnych nie przecinających się wielokątów z bokami wyrównanymi do osi można utworzyć za pomocą danego łańcucha?
Spójrzmy na przykład. Rozważmy szczególny łańcuch składający się z 8 prętów o długości 1 i 2, które możemy przedstawić jako [1, 1, 2, 2, 1, 1, 2, 2]
. Do rotacji i tłumaczeń istnieje tylko 8 możliwych poliominoesów (liczymy różne odbicia):
Ten pierwszy pręt jest granatowy, a następnie przemierzamy wielokąt w kierunku przeciwnym do ruchu wskazówek zegara .
Kierunek obrotu nie wpływa na wynik w powyższym przykładzie. [3, 1, 1, 1, 2, 1, 1]
Zastanówmy się jednak nad innym łańcuchem , który daje następujące 3 poliominoes:
Zauważ, że nie uwzględniamy odbicia ostatniego poliomino, ponieważ wymagałoby to przejścia w prawo.
Gdybyśmy mieli bardziej elastyczny łańcuch o tej samej długości, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
faktycznie bylibyśmy w stanie utworzyć oba odbicia wśród niektórych innych poloninoów, w sumie 9:
Wyzwanie
Biorąc pod uwagę opis łańcucha, jako szyku lub podobnego elementu, określ liczbę różnych poliominoesów, które możesz utworzyć (do rotacji i translacji) za pomocą prętów w porządku , poruszając się po obwodzie w kierunku przeciwnym do ruchu wskazówek zegara.
Napisz pełny program i dołącz polecenia do kompilacji (jeśli dotyczy) i uruchom kod z wiersza poleceń. Dołącz także link do bezpłatnego kompilatora / tłumacza dla twojego języka.
Twój program powinien odczytać dane wejściowe ze STDIN. Pierwsza linia zawiera całkowitą M . Kolejne M linii to przypadki testowe, z których każda będzie oddzieloną spacją listą długości prętów. Twój program powinien wypisać M linii do STDOUT, z których każda składa się z jednej liczby całkowitej - liczby różnych poliominoes, które można utworzyć.
Musisz użyć tylko jednego wątku.
Twój program nie może zużywać więcej niż 1 GB pamięci w dowolnym momencie. (Nie jest to całkowicie ścisły limit, ale będę monitorować wykorzystanie pamięci pliku wykonywalnego i zabijać każdy proces, który konsekwentnie zużywa więcej niż 1 GB lub skoki znacznie powyżej niego).
Aby zapobiec nadmiernej ilości obliczeń wstępnych, Twój kod nie może być dłuższy niż 20 000 bajtów i nie wolno odczytywać żadnych plików.
Nie wolno również optymalizować pod kątem wybranych wybranych przypadków testowych (np. Przez zakodowanie wyników ich). Jeśli podejrzewam, że tak, zastrzegam sobie prawo do generowania nowych zestawów testów porównawczych. Zestawy testowe są losowe, więc wydajność Twojego programu na nich powinna być reprezentatywna pod względem działania na dowolnych danych wejściowych. Jedynym założeniem, jakie możesz przyjąć, jest to, że suma długości wędek jest parzysta.
Punktacja
Dostarczyłem zestawy wzorcowe dla łańcuchów N = 10, 11, ..., 20 prętów. Każdy zestaw testowy zawiera 50 losowych łańcuchów o długości od 1 do 4 włącznie.
Twój wynik główny to największy N, dla którego Twój program ukończy cały zestaw testów w ciągu 5 minut (na moim komputerze, pod Windows 8). Przerywaczem remisów będzie rzeczywisty czas zajęty przez program na tym zestawie testowym.
Jeśli ktoś pobije największy zestaw testowy, będę dodawał większe.
Przypadki testowe
Możesz użyć następujących przypadków testowych, aby sprawdzić poprawność swojej implementacji.
Input Output
1 1 0
1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 3
1 1 1 1 1 1 1 1 1 1 9
1 1 1 1 1 1 1 1 1 1 1 1 36
1 1 1 1 1 1 1 1 1 1 1 1 1 1 157
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 758
1 1 2 2 1 1 2 2 8
1 1 2 2 1 1 2 2 1 1 23
1 1 2 2 1 1 2 2 1 1 2 2 69
1 2 1 2 1 2 1 2 3
1 2 1 2 1 2 1 2 1 2 1 2 37
1 2 3 2 1 2 3 2 5
1 2 3 2 1 2 3 2 1 2 3 2 23
3 1 1 1 2 1 1 3
1 2 3 4 5 6 7 1
1 2 3 4 5 6 7 8 3
1 2 3 4 5 6 7 8 9 10 11 5
2 1 5 3 3 2 3 3 4
4 1 6 5 6 3 1 4 2
3 5 3 5 1 4 1 1 3 5
1 4 3 2 2 5 5 4 6 4
4 1 3 2 1 2 3 3 1 4 18
1 1 1 1 1 2 3 3 2 1 24
3 1 4 1 2 2 1 1 2 4 1 2 107
2 4 2 4 2 2 3 4 2 4 2 3 114
Znaleźć plik wejściowy z tymi tutaj .
Tabela liderów
User Language Max N Time taken (MM:SS:mmm)
1. feersum C++ 11 19 3:07:430
2. Sp3000 Python 3 18 2:30:181
źródło
Odpowiedzi:
C ++ 11
Aktualizacje: Dodano pierwszą linię,
c
która wybucha wcześnie, jeśli odległość jest zbyt daleko od początku (co było celem zmiennejrlen
, ale zapomniałem napisać ją w pierwszej wersji). Zmieniłem to, aby zużywać znacznie mniej pamięci, ale kosztem czasu. Teraz rozwiązuje dla mnie N = 20 w niecałe 5 minut.Połącz z
źródło
#define
s ThoPython 3 (z PyPy ) - N = 18
Uruchom z
./pypy <filename>
.To jest implementacja referencyjna, którą napisałem, omawiając pytanie z Martinem. Nie został stworzony z myślą o szybkości i jest dość zuchwały, ale powinien zapewnić dobrą podstawę do rozpoczęcia.
N = 18 zajmuje około 2,5 minuty na moim skromnym laptopie.
Algorytm
Obroty są sprawdzane przez przekształcenie każdego kształtu w serię
F
do przodu,A
do obrotu przeciwnie do ruchu wskazówek zegara iC
do obrotu zgodnie z ruchem wskazówek zegara w każdym punkcie sieci na granicy kształtu - nazywam to ciągiem kątowym . Dwa kształty są obrotowo identyczne, jeśli ich ciągi kątowe są cyklicznymi permutacjami. Zamiast zawsze sprawdzać to, porównując bezpośrednio dwa ciągi kątowe, gdy znajdziemy nowy kształt, przed zapisaniem przekształcamy go w postać kanoniczną. Kiedy mamy nowego kandydata, przechodzimy do formy kanonicznej i sprawdzamy, czy już ją mamy (wykorzystując w ten sposób haszowanie, zamiast iteracji przez cały zestaw).Łańcuch kątowy służy również do sprawdzenia, czy kształt jest uformowany przeciwnie do ruchu wskazówek zegara, upewniając się, że liczba
A
s przekracza liczbęC
s o 4.Samo przecięcie jest naiwnie sprawdzane poprzez przechowywanie każdego punktu sieci na granicy kształtu i sprawdzanie, czy punkt jest odwiedzany dwukrotnie.
Algorytm rdzenia jest prosty, umieszczając pierwszy pręt po prawej stronie, a następnie wypróbowując wszystkie możliwości dla pozostałych prętów. Jeśli pręty dojdą do punktu, który jest zbyt daleko od początku (tj. Suma pozostałych długości prętów jest mniejsza niż odległość punktu Manhattan od punktu początkowego), wówczas przedwcześnie przestajemy szukać tego poddrzewa.
Aktualizacje (najnowsze pierwsze)
źródło