31 / 31
Feb 2019

Jeżeli chodzi o zadanie “Kwadratowy świat II” to szczerze mówiąc spodziewaliśmy się większej liczby AC. W zadaniu mamy n punktów i musimy stwierdzić ile różnych kwadratów równoległych do osi układu współrzędnych możemy ułożyć. Mamy również zagwarantowane, że punkty się nie powtarzają.

Rozwiązanie naiwne to oczywiście 4 zagnieżdżone pętle, z których każda wybiera 1 wierzchołek kwadratu. Mając wybrane 4 wierzchołki sprawdzamy czy tworzą kwadrat równoległy do osi układu współrzędnych. Takie rozwiązanie ma złożoność O(n^4), biorąc pod uwagę, że maksymalna wartość n wynosi 10^6 to nie ma możliwości żeby zmieściło się ono w czasie bo w 4s musielibyśmy wykonać 10^24 operacji.

Rozwiązanie naiwne moglibyśmy przyspieszyć stosując wyszukiwanie binarne. Jeżeli mamy wybrane 2 wierzchołki, które tworzą bok kwadratu to współrzędne pozostałych 2 możemy sobie łatwo wyznaczyć, a następnie za pomocą wyszukiwania binarnego sprawdzić czy takie punkty występują w naszym zbiorze. Pojedyncze wyszukiwanie binarne na zbiorze 10^6 elementów wynosi maksymalnie 20 operacji, co oznacza, że jest to bardzo duże przyspieszenie w porównaniu z wyszukiwaniem liniowym. Złożoność takiego podejścia wynosi O(2 * n^2 * log(n)) czyli dla maksymalnych danych byłoby to 4 * 10^13 operacji. To dalej jest za dużo.

W tym momencie możemy zauważyć, że nawet gdyby udało nam się zejść do złożoności O(n^2) to prawdopodobnie i tak dostaniemy TLE, gdyż będzie to 10^12 operacji. Wiemy jednocześnie, że nie rozwiążemy tego zadania bez wyznaczenia co najmniej 1 boku kwadratu. Co zatem należy zrobić?

Kluczowa obserwacja jest taka, że powierzchnia, na której występują punkty jest mała. W pionie lub poziomie nie będziemy mieli nigdy więcej niż 2001 punktów. Wiemy również, że nasz kwadrat będzie miał wszystkie boki równoległe do jednej z osi. W związku z powyższym łatwo można wywnioskować, że nie opłaca się tworzyć boku z punktów, które nie mają takiej samej wartości współrzędnej x albo y. Skorzystajmy z tych faktów. Posortujmy punkty rosnąco po współrzędnej x, a jeżeli punkty mają taką samą współrzędną x to rosnąco po współrzędnej y. Mając posortowane punkty wyznaczamy bok naszego kwadratu stosując dwie zagnieżdżone pętle tak jak to robiliśmy w poprzednich podejściach. Różnica w tym rozwiązaniu polega na tym, że wewnętrzną pętlę przerywamy w momencie, gdy trafimy na punkt o innej współrzędnej x niż współrzędna x punktu wybranego przez pętlę zewnętrzną. Pseudokod poniżej:

for i = 0 to n - 1 do
  for j = i + 1 to n - 1 do
    if P[j].x != P[i].x then
      break
    // Tutaj sprawdzamy czy istnieją pozostałe 2 punkty, które utworzą kwadrat

Takie podejście gwarantuje nam, że w najgorszym wypadku wykonamy 2001^2 * (n / 2001) operacji. Dla ułatwienia obliczeń załóżmy, że mamy po 2000 punktów w 500 kolumnach. Da to nam 2000^2 * (10^6 / 2000) = 2 * 10^9 operacji. Biorąc pod uwagę limit 4s i szybkość Cube’a (serwer sprawdzający SPOJa) jest to akceptowalna wartość. Pozostaje kwestia szybkiego sprawdzenia czy istnieją pozostałe 2 punkty, które mają utworzyć kwadrat z naszym bokiem. Znowu korzystając z tego, że powierzchnia jest mała możemy to zrobić w czasie stałym. W tym celu tworzymy sobie tablicę o rozmiarach 2001 na 2001 elementów i zapisujemy wartość true w komórkach, w których są punkty. Oczywiście współrzędne punktów musimy zamienić na nieujemne dodając 1000 do każdej z nich.

Takie rozwiązanie gwarantowało AC.

Dzięki za wyjaśnienie
Wydawało mi się, ze właśnie tak to próbowałem rozwiązać. Muszę jeszcze raz zajrzeć do mojego kodu

Z tego co widzę w Twoim ostatnim zgłoszeniu to nie porządkujesz punktów wg. współrzędnych tylko dla każdego punktu starasz się odpowiednio przechodzić tablicę z punktami. Obawiam się, że przy takim podejściu problemem wydajnościowym może być to, że za dużo “skaczesz” po pamięci, ale nie mam 100% pewności bo to była taka 2 minutowa analiza Twojego rozwiązania :slight_smile: Jak jesteś zainteresowany to wklejam link do mojego rozwiązania: https://ideone.com/1OC2Vh23

No to widzę mocno przekombinowałem. Moje pierwsze zgłoszenie było najbliżej prawdy. Kolejne to już była zbędna akrobatyka programistyczna :wink:

Edit. Dla potomnych: korzystanie z unordered_map wprowadza spory narzut w porównaniu ze zwykłą tablicą. Nie spodziewałem się, ze to robi az taką różnicą.

Kolejny “FRAKATAL” i miało być tak pięknie - znaczy się ja zajmuję pierwsze miejsce - no ale niestety wyszło gorzej niż zwykle czyli tylko 8 zadań zaliczonych .

Rozpocząłem też kilka kolejnych które które wydawały się “łatwe” a niestety się od nich odbiłem

  • pierwsze zadanie to “25” w którym nie ogarniałem treści, a po pierwszym wysłaniu rozwiązania zorientowałem się że rozpatruje tylko przypadek z końcówka 25 na końcu liczby ( a pomijam 00, 50, 75 ). Postanowiłem czekać ( w tym czasie rozwiązywać inne zadania ) na jakąś dyskusję pod zadaniem . Ta rozpoczęła się dość późno i dopiero w tedy zorientowałem się o co dokładnie chodzi autorowi - zadanie zostawiłem sobie na “później” czyli nie zrobiłem .
  • Zadanie “Haft” - całkiem dobre zadanie bo w pierwszej chwili myślałem że przejdzie rozwiązanie typu “brutal” . Niestety to że wydaje się łatwe nie znaczy że jest - i po otrzymaniu przekroczenia czasu trzeba było się dokładniej przyjrzeć problemowi . Udało mi się wpaść na pomysł jak przyspieszyć algorytm w momencie testowania czy po każdej stronie od centrum w danej odległości jest nadal haft . Taka optymalizacja jednak nadal nie mieściła się w limicie czasu . I tu nastąpił kryzys optymalizacyjny - bo mój algorytm na końcu testował czy każde pole z haftem zostało wydziergane - a więc nadal w skrajnym przypadku ustawiał od 1 do N wyhaftowanie danego pola . Nie potrafiłem tego mozolnego ustawiania obejść .
  • Zadanie “Czworościan” - uuuuu … pierwsze co zrobiłem to sprawdziłem Wikipedie - i odbiłem się od tego co przeczytałem . Próbowałem w ciągu tych 32 jeszcze kilka razy zrozumieć co tam powypisywali ale ogólnie “wyznacznik macierzy” mnie przeraził i nie wiedziałem jak się do tego zabrać . Po konkursie postanowiłem zrobić to zadanie , obejrzałem 2 filmy na yt i zadanko rozwiązane – nowa wiedza w głowie .
  • Zadanie “Sok jabłkowy” - dokładnie sam nie wiem co nie poszło w tym zadaniu . U mnie dla maks testów ( 1000 jedynek w danych wejściowych ) robiło się 2 sek ( na starym lapku ) . “Brutal” z optymalizacją na sumy prefiksowe jednak nie przeszedł .
  • Zadanie “Kwadratowy śwwiat II” - domyśliłem się że sprawdzanie wszystkich kombinacji nie przejdzie więc wrzucałem liczby po x i y do tablicy o danym numerze N ( coś jak sortowanie kubełkowe dla każdej osi ) - no i tu dalej zwarcie w mózgu bo nie mogłem wymyślić jak dalej zoptymalizować .

Najgorsze jest to że na kilka godzin przed końcem konkursu już się poddałem ( miałem całą serie podejść do zadań które nie wiedziałem jak zoptymalizować ) .

Podsumowując - czekam na kolejną edycję - może pójdzie mi lepiej niż jak zwykle .

“Kwadratowy świat”, “Jąkała”, “Zlot kolekcjonerów monet” - proste, przyjemne zadanka w sam raz na rozgrzewkę przed pozostałymi :slight_smile:

“Pętla” - po pierwszym przeczytaniu (po łebkach) zadanie wydawało się proste (dwuwymiarowa tablica booli, sprawdzanie czy dany punkt był już odwiedzany), niestety czwarty test rozwiał moje nadzieje na kolejne zaliczone łatwe zadanie…

“25” - zadanie, które mnie rozwaliło. Siedziałem nad nim kilka godzin, wymyślając różne testy, w końcu doszedłem do wersji kodu, która dla każdego mojego testu daje dobry wynik, jednak nadal sędzia nie przyjmował :frowning: Jakby ktoś miał czas, to prosiłbym o jakąś wskazówkę co przeoczyłem (z góry przepraszam za syfiasty kod, tak to jest jak się najpierw pisze, potem myśli… <tu był link do kodu, ale się zmył :slight_smile:> ).

Warto też wspomnieć o zadaniu “czworościan” - próbowałem sobie różne rzeczy wyobrażać, szukałem w internecie jakichś wskazówek, nic z tego. Aż w końcu podstawiłem dane do pierwszego znalezionego wzoru na objętość czworościanu i dawał dobry wynik :slight_smile:

Ogółem zadania bardzo ciekawe, udało mi się rozwiązać 9 na 20, co nie jest moim zdaniem bardzo złym wynikiem. Niestety ta nieszczęsna 25 mnie zniechęciła, w innym wypadku pewnie bym spróbował rozwiązać jeszcze kilka. Wielki szacun dla organizatorów, z niecierpliwością czekam na następną edycję Fraktala, w której mam nadzieję, że pobiję swój dotychczasowy wynik.

Wesołego Nowego Roku! :slight_smile:

Masz błąd na tym samym teście, na którym wywalała się większość rozwiązań. Jego uproszczona wersja wygląda tak:
50117
Odpowiedzią jest 5, Twój program zwraca 6. Co ciekawe dla 5017 odpowiedź masz prawidłową. Rzeczywisty test w zadaniu prezentuje się następująco:
5013611499391318666414491496888118839396836143811634996198389384634133991634493896963181689646319187
Odpowiedzią jest 100, Twój program zwraca 196.

Serdeczne dzięki za podpowiedź, zadanie to spędzało mi sen z powiek :slight_smile:

A ja proszę o podpowiedź do pętli, męczy mnie a nijak nie mogę wpaść jak to ugryźć :slight_smile:

Uwaga! Poniższe rozwiązanie jest niepoprawne ponieważ Mariusz zmodyfikował zadanie po moich testach. Dzisiaj wrzucę poprawione omówienie. Przepraszam za wprowadzenie w błąd.

W tym zadaniu naszym celem jest stwierdzenie czy istnieje spójny niepusty podciąg trasy Jasia, który utworzy pętlę.

Pierwsze spostrzeżenie jest takie, że trasa jaką pokonał Jasiu jest krótka i zawiera co najwyżej 100 znaków, a zatem spokojnie możemy zbadać wszystkie możliwe podciągi.

Przejdźmy zatem do weryfikacji czy dany podciąg jest poprawną pętlą (łamaną). Sprawdźmy definicję łamanej.

Łamaną nazywamy figurę geometryczną, która jest sumą skończonej liczby odcinków takich, że każde dwa kolejne mają wspólny koniec oraz:

  • każde dwa kolejne odcinki i tylko dwa kolejne odcinki mają wspólny koniec,
  • żadne dwa następujące po sobie odcinki nie są zawarte w jednej prostej.

Zgodnie z treścią zadania nasz bohater może na trasie wykonywać skręty o 90 lub 180 stopni. Jednak jak widzimy w definicji łamanej nawroty (skręty o 180 stopni) spowodują, że dana figura nie będzie już łamaną ponieważ 2 następujące po sobie odcinki będą zawarte w jednej prostej. I to jest główny haczyk w tym zadaniu. W związku z powyższym pierwszym etapem jest sprawdzenie czy w wybranym podciągu trasy występują nawroty czyli: NS, SN, WE lub EW. Jeżeli występują to dany podciąg nie będzie poprawną pętlą.

Jeżeli nawroty nie występują to pozostało nam sprawdzić czy po przejściu całego podciągu wróciliśmy do punktu, z którym się zaczynał. Można to zrobić np. zliczając liczbę wystąpień liter N, S, E, W. Jeżeli N = S i E = W tzn. że wróciliśmy do punktu wyjścia, a co za tym idzie znaleźliśmy poprawną pętlę.

Wybranie podciągu do sprawdzenia ma złożoność O(n^2), sprawdzenie tego podciągu O(n), a zatem całość ma złożoność O(n^3) co przy maksymalnej wartości n = 100 jest w zupełności wystarczające.

jak dla mnie to rozwiązanie zadania pętla ma zbyt dużą złożoność, używając tablicy dwuwymiarowej mam rozwiązanie o złożoności O(n)

Oczywiście, że można. Możemy założyć sobie, że startujemy z punktu 100,100 i generować kolejne współrzędne. Wchodząc na dany punkt sprawdzamy czy byliśmy na nim wcześniej (co możemy odczytać właśnie z tablicy 2 wymiarowej) i jednocześnie sprawdzamy czy to nie jest nawrót itd.

Jednak specjalnie opisałem wolniejsze rozwiązanie, żeby uczyć ludzi, że nie ma sensu wytaczać armaty na muchy jeżeli zadanie tego nie wymaga. Ostatecznie drugim kryterium po liczbie rozwiązanych zadań jest czas ich rozwiązania.

Julia, testowałem Twoje ostatnie zgłoszenie i np. dla takiego testu:

1
NSEESSWWNNS

Twój program zwraca NIE, a powinien TAK, bo mamy pętlę EESSWWNN począwszy od 3 znaku.

Dopiero się przebiłem przez łatwe zadania. Bardzo fajnie napisane, gratulacje. Mimo już X edycji było czuć w nich dużo świeżości.

Jak dla mnie termin kolidował z wyjazdem do domu rodzinnego i lepieniem świątecznych pierogów, ale cieszę się, że frekwencja dopisała.

Zadanie “Czworościan” było pierwszym fraktalowym zadaniem “szkolno-geometrycznym”, które rozwiązałem nie posiłkując się internetami. Odbiłem się od Wikipedii i od wyników duckduckowania więc uznałem, że w końcu nadszedł ten straszny dzień i postanowiłem pomyśleć a nie pałować geometrię na konkursie. Ku mojemu zaskoczeniu szybko poszło.

No ale od czego były inne zadania, np. w jednym przez ok 8h szukałem błędu (wysyłając ileś zgłoszeń z kosmetycznymi poprawkami w stylu “o to musiało chodzić autorowi”) i w końcu znalazłem - zwracałem long longa i przypisywałem go do inta :wink: Ale myślę, że nawet pomimo takiej wtopy mój wynik jest o.k. tym bardziej, że od dawna nie robiłem zadań tego typu.

Czekamy na Fraktal XI.

1 month later

Ja jeszcze nie. Ale to wina min arduina, skubany zabiera trochę czasu ;-). Wczoraj zrobiłem kolejne podejście do czworościanu i znowu głupi błąd, ale w końcu udało mi się wyprowadzić prawidłowy wzór. Możliwe, że rozwiązanie jest gdzieś w necie, lub w tym wątku, ale póki sam się nie uporam z pętlą, nie będę kombinował. :wink:

PS
Oczywiście zadania miód malina, Brawo you!

Jeżeli jest, albo miało to być dowcipne, to pewnie straciłem poczucie humoru i wcale ale to wcale mnie to nie rozbawiło. Nie rozumiem też, czemu zmarnowałeś czas, przecież udział i rozwiązywanie zadań nie jest obowiązkowy ale jest całkowicie dobrowolny. Więc zamiast tracić czas, mogłeś w tym czasie robić cokolwiek innego. Mogłeś na przykład wyjść na spacer, pojeździć na rowerze albo pobiegać. Pewnie uważasz, że to też strata czasu, ale to właśnie jest dobre przede wszystkim dla zdrowia.

Nie zaprzeczam, że mój post może być odebrany jako chamski. Z drugiej strony sądzę, że zapoznanie się z treścią komentarzy pod tym zadaniem (https://www.spoj.com/FRAKTAL/problems/FR_10_04/13), a w szczególności z zawartością ostatniego z nich:

2018-12-22 15:03:23 Maciej Boniecki

  1. Liczby na wejściu nie zawierają zer wiodących
  2. Przyznaje, że zgubiła mnie pewność siebie i nie sprawdziłem definicji rzędu wielkości. Jego użycie w treści było błędem, bo rząd wielkości to potęga 10 najbliższa danej liczbie. W zadaniu chodzi o to żeby największa potęga 10, która nie jest większa od danej liczby była zawsze taka sama. Przepraszam za wprowadzenie w błąd :frowning:

może się przyczynić do zmiany nastawienia. Prawdopodobnie nadal będzie ciężko uznać mój post za zabawny, ale może chociaż nabierze on trochę sensu.

Myślę, że wiele zależy od podejścia, oraz od postawionego celu. Niektórzy uczestnicy konkursu biorą udział dla zabicia nudy, inni żeby zmierzyć się ze znajomymi. Jeszcze inni stawiają poprzeczkę nieco wyżej: jedni będą chcieli skończyć na podium, drudzy będą dokładać wszelkich starań żeby wygrać.
Postawmy się teraz na miejscu uczestnika, który celuje w top 3. Wydaje mi się, że dla takiej osoby umiejętne zarządzanie dostępnym czasem jest jednym ze środków do celu. Napotkanie podczas konkursu niekorzystnych czynników zewnętrznych (takich jak błędna treść, lub niepoprawne testy) spowalnia dążenie do upragnionego celu. Czy w tym przypadku nie można stwierdzić, że te czynniki przyczyniły się do straty/zmarnowania cennego czasu?

Pozostawię to bez komentarza.

Myślę, że nie ma co wracać do tematu. Pomyłka niestety była, przeprosiłem i życie się toczy dalej :slight_smile:

Suggested Topics

Topic Category Replies Views Activity
Konkursy 8 234 6h

Want to read more? Browse other topics in Konkursy or view latest topics.