Wprowadzenie
Jesteś sam na wyspie. Reszta ludzkości nie żyje ( prawdopodobnie z powodu błędu w kodzie użytkownika12345 ). Horda piratów zombie dotarła na twoją wyspę i są nieograniczone. Czas skopać tyłek lub żuć gumę do żucia, a wy wszyscy jesteście poza gumą do żucia.
Problem
Nasz scenariusz zagłady jest opisany przez 2 liczby całkowite w jednym wierszu m
i n
. Na twojej wyspie znajdują się posterunki o numerach od 1 do m
. Poniższe n
linie zawierają po trzy liczby całkowite x
, y
i z
rozdzielone przez przestrzeń. x
i y
są unikalnymi identyfikatorami dwóch placówek oraz z
liczbą zombie, które można spotkać na drodze między nimi.
Podróżując ścieżką, tracisz z
amunicję i zabijasz z
zombie. Jeśli ponownie pokonasz tę samą ścieżkę, napotkasz niestety taką samą liczbę zombie. Wszystkie placówki generują amunicję +1 za każdym razem, gdy przemierzasz ścieżkę. Zaczynasz od 100 amunicji w placówce 1. Wszystkie placówki zaczynają się od 0 amunicji. Umierasz natychmiast, jeśli nie istnieje ścieżka, dla której twoja amunicja jest większa niż liczba zombie na tej ścieżce, a pozostała część amunicji zamienia się w zabójstwa. Takie jest twoje ostateczne stanowisko.
Napisz program, który wyświetli maksymalną liczbę zombie, które możesz zabić dla danego scenariusza. Jeśli możesz zabić nieskończoną liczbę zombie, po prostu wyjdź x
.
Przykładowe dane wejściowe
5 6
1 2 4
2 3 4
3 1 4
2 4 10
2 5 10
1 1 50
Przykładowy wynik
x
Założenia
- Ścieżka będzie znajdować się między dwoma ważnymi placówkami. To znaczy 1 <=
x
/y
<=m
- Jeśli ścieżki pomiędzy
x
iy
nie ma na liście, nie można jej pokonać - Ścieżka jest dwukierunkowa
- 1
m
<<= 100 - 1
n
<<= 500 - Dane wejściowe muszą być dostarczane przez stdin, odczytane z pliku lub zaakceptowane jako jedyny argument programu i muszą dokładnie odpowiadać formatowi przykładu
- Środowisko wykonawcze twojego programu może być dowolnie duże, ale musi być możliwe do skończenia
Wygrywa kod z najmniejszą liczbą znaków!
1
początkową 0 amunicją? Czy wykres jest niekierunkowy?1->1
kosztuje 49 amunicji, a cykl1->2->3->1
kosztuje 3 amunicję w dłuższej perspektywie.Odpowiedzi:
Java ( mniej groteskowa:
841552913301)Dobrze. Zasadniczo jestem zawstydzony, nikt nie przedstawił rozwiązania. Kilka dni temu zacząłem próbować rozwiązać ten problem, b / c to świetnie. . Kliknij ten link, aby obejrzeć moje postępy w GitHub.
Edytować
Nowa wersja solvera, znacznie bardziej „golfowa”, z poprawionym sprawdzaniem cyklu zidentyfikowanym przez MT0. Obsługuje również trasy szybkiego przekazywania, dostrajane przez zmianę ilości pamięci dostępnej dla maszyny wirtualnej. Ostatnia DUŻA edycja: zdałem sobie sprawę, że miałem kilka innych drobnych błędów indeksu i przedwczesnych optymalizacji, co spowodowało, że nie wziąłem pod uwagę dość dużej liczby rodzajów zwycięstw. To jest naprawione, ostrożnie. Nowa wersja jest zarówno mniejsza, jak i niższa. W przypadku naszej trasy odniesienia
java -Xmx2GB ZombieHordeMin
trik wygląda całkiem nieźle (uwaga, zajmie to trochę czasu).Fajny faktoid
W fascynującym wydaniu jest WIELE rozwiązań o długości 24, a mój solver znajduje inny niż MT0, ale zasadniczo identyczny, z tym wyjątkiem, że zaczyna się od odwiedzenia innych placówek powiązanych z
1
. Fascynujący! Całkowicie przeciwstawia się ludzkiej intuicji, ale doskonale obowiązuje.Najważniejsze informacje o rozwiązaniu
Więc tu jest moje. Jest (częściowo) grał w golfa, b / c jest wykładniczym solwerem o prawie brutalnej sile. Używam algorytmu IDDFS (iteracyjne pogłębianie pierwszego wyszukiwania), więc jest to świetny ogólny solver, który nie przeskakuje, więc rozwiązuje obie części pytania OP, a mianowicie:
Daj mu wystarczającą moc, pamięć i czas, a zrobi to samo, nawet mapy powolnej śmierci. Spędziłem trochę czasu na ulepszaniu tego solvera i chociaż można zrobić więcej, teraz jest trochę lepiej. Zintegrowałem również porady MT0 dotyczące najlepszego rozwiązania z nieskończonymi zombie i usunąłem kilka przedwczesnych optymalizacji z mojego narzędzia do sprawdzania wygranych, które uniemożliwiły poprzedniej wersji znalezienie tego, a teraz znajduję bardzo podobne rozwiązanie do opisanego MT0.
Kilka innych głównych atrakcji:
Oprzyrządowałem algorytm, aby oglądanie było bardziej interesująceRemoved do gry w golfa . Kliknij jeden z linków do github, aby zobaczyć wersję bez golfa.Jest też wiele komentarzy, więc zachęcamy do ponownego wdrożenia własnego rozwiązania w oparciu o moje podejście lub pokaż mi, jak należy to zrobić!Historia solvera
Kod (golfowy)
Do kodu (pobierz wersję bez golfa tutaj lub tutaj ):
Pobierz kod z github tutaj, aby śledzić wszelkie zmiany, które wprowadzam. Oto kilka innych map, z których korzystałem.
Przykład wyjściowy
Przykładowe dane wyjściowe dla rozwiązania referencyjnego:
Przeczytaj wynik trasy w ten sposób
step
::source
,route-to-get-here
-ammo
. W powyższym rozwiązaniu odczytałbyś to jako:0
, na posterunku1
z amunicją100
.1
użyj trasy,1
aby dostać się do placówki3
z zakończoną amunicją97
2
użyj trasy,1
aby dostać się do placówki1
z zakończoną amunicją95
Notatki końcowe
Mam nadzieję, że trudniej pokonałem moje rozwiązanie, ale WYPRÓBUJ! Użyj go przeciwko mnie, dodaj trochę przetwarzania równoległego, lepszą teorię grafów itp. Kilka rzeczy, które według mnie mogą poprawić to podejście:
wytnij martwe trasy. Moje obecne rozwiązanie nie „pamięta”, że dana trasa jest ślepa i za każdym razem musi ją odkrywać na nowo. Lepiej byłoby śledzić najwcześniejszy moment na drodze, na której śmierć jest pewna, i nigdy nie przekraczać jej.zrobił to...Każde inne rozwiązanie, które wymienia pamięć na czas lub umożliwia agresywne unikanie podążania ślepymi drogami.też to zrobiłem!źródło
Kilka abstrakcyjnych notatek na temat rozwiązania
Jeśli będę miał czas, przekonwertuję to na algorytm ...
Dla danego wykresu
G
istnieje połączony pod-wykresG'
zawierający miasto1
. Jeżeli istnieje nieskończona rozwiązanie to będzie istnieć podłączony sub-wykresG''
zG'
zawierającyV
miast iP
drogami.Ścieżki
P
odG''
może być podzielony w taki sposób,{p}
zawiera ścieżkę, która ma wówczas minimalne koszty wszystkich ścieżekP
iP/{p}
to wszystkie pozostałe ścieżki (tworzące drzewa rozpinającego lub ewentualnie cykl). Jeśli założymy, żep
nie jest to pętla krawędzi (łącząca oba końce z tym samym miastem), wówczas połączy dwa miasta (v1
iv2
) i będzie kosztowaćc
amunicję, wtedy (ocalały) będziecie mogli przejść od iv1
dov2
tyłu za całkowity koszt2c
amunicji a to zwiększy amunicję we wszystkich miastach o 2 (dla całkowitego wzrostu2|V|
wewnątrzG''
- niektóre z nich zostaną zebrane zv1
iv2
).Jeśli podróżujesz z
v1
dov2
iz powrotem dov1
wielokrotności (m
) razy, a następnie wybrać się na wycieczkę zv1
wzdłuż krawędziP/{p}
, aby odwiedzić wszystkie miasta inne niżv1
av2
przed powrotem dov1
a to wymagan
ścieżki do osiągnięcia (gdzie|P/{p}| ≤ n ≤ 2|P/{p}|
ponieważ nigdy nie powinno trzeba przemierzać ścieżki więcej niż dwa razy) kosztem,k
a miasta zyskają2m|V|
amunicję (ponownie niektóre z nich zostaną zebrane podczas przemierzania).Biorąc to wszystko pod uwagę, możesz stwierdzić, czy nieskończone rozwiązanie jest potencjalnie możliwe, jeśli wtedy koszt
k + 2mc
jest równy lub niższy niż całkowita nagroda2(m+n)|V|
.Problem wiąże się z dodatkową złożonością polegającą na tym, że:
1
do{p}
pierwszej iteracji i będziesz musiał uwzględnić ten koszt; im
in
są na tyle niskie, że nie zabraknie ci amunicji, zanim będziesz w stanie przejść przez pierwszą iterację, ponieważ pierwsza iteracja będzie miała wyższy koszt niż kolejne iteracje).Prowadzi to do 24-ścieżkowego rozwiązania neutralnego pod względem kosztów do przykładu w pytaniu (liczby to odwiedzone miasta):
źródło