This post comes from the first version of this blog.
Please send me an email if anything needs an update. Thanks!
Z lekkim poślizgiem publikuję analizę kolejnego zadania z konkursu “Potyczki Algorytmiczne” 2011 - 1B “Wieże”. Zadanie nie było trudne, aczkolwiek dosyć ciekawe. Nie udało mi się uzyskać jakiegoś specjalnie optymalnego wyniku, aczkolwiek pomyślnie przeszedłem wszystkie testy i kolejne 10 punktów wylądowało na moim koncie. Warto czasem rozruszać komórki mózgowe, dlatego zapraszam do lektury.
Fotografia: Vittis from Lithuania, CC-BY;
Potyczki Algorytmiczne 2011: Zadanie "Wieże".
Treść zadania jest nastepująca:Po długich staraniach Bajtek zdołał rozmieścić n wież na szachownicy rozmiaru n×n, tak że żadne dwie wieże nie szachują się. Dla przypomnienia: wieża szachuje wszystkie pola szachownicy znajdujące się w tym samym wierszu lub w tej samej kolumnie co ona.Wejście:Niestety, chłopiec przypadkowo potrącił szachownicę, przez co niektóre z wież poprzewracały się i spadły. Czy pomógłbyś mu ustawić te wieże z powrotem? Bajtek prosi, żeby nie ruszać wież, które wciąż stoją na szachownicy.
W pierwszy wierszu standardowego wejścia znajduje się jedna liczba całkowita n (2 <= n <= 1 000), oznaczająca rozmiar szachownicy. Dalej następuje opis ustawienia wież na szachownicy: kolejne n wierszy zawiera po n znaków każdy. Znak ‘.’ oznacza puste pole, a litera ‘W’ reprezentuje pole zajmowane przez wieżę.Wyjście:Możesz założyć, że na szachownicy stoi w wież, przy czym 1 <= w <= n − 1, oraz że żadna para stojących wież nie szachuje się.
Twój program powinien wypisać na standardowe wyjście reprezentację odpowiednio zapełnionej szachownicy w postaci n wierszy zawierających po n znaków ‘.’ lub ‘W’ każdy. Na planszy powinno występować dokładnie n znaków ‘W’ reprezentujących wieże, przy czym w wież powinno stać dokładnie na takich samych pozycjach jak na wejściu. Żadne dwie wieże nie mogą się szachować. Jeśli istnieje więcej niż jeden sposób dostawienia n − w wież, Twój program może wypisać dowolny z nich.Przykład:
Dla danych wejściowych:``` 8 ........ .....W.. ..W..... .......W W....... ........ .W...... ........ ```
jednym z poprawnych wyników jest:
....W...
.....W..
..W.....
.......W
W.......
......W.
.W......
...W....
Zobaczmy, jak można rozwiązać to zadanie.
Rozwiązanie.
Moje rozwiązanie polegało na zaalokowaniu wektora o rozmiarze n * (n + 2) dla szachownicy o rozmiarze n. Pierwsze n elementów zawierało informację o tym, czy w danym wierszu znajduje się wieża, kolejne w elementów odnosiło się do kolumn. Reszta pamięci była zarezerwowana na całą szachownicę. Dane były typu bool, a więc przechowywałem tylko informację o tym, czy na danym polu / kolumnie / wierszu stoi pionek.Pętla rozwiązująca zadanie musiała analizować zawartość pierwszych dwóch n elementów i w momencie, kiedy znalazła “pusty” wiersz i kolumnę, stawiała tam pionek i oznaczała wiersz i kolumnę jako zajętą.
Oto kod, jaki wyprodukowałem:
|
|
Optymalizacje.
Analizując zadanie już po oddaniu zauważyłem, że prawdopodobnie o wiele szybszą metodą byłoby analizowanie pozycji wież tylko po ich współrzędnych, zamiast operować na całej szachownicy. Plansza mogła mieć maksymalnie 1000 pól, co w najgorszym przypadku daje nam milion [1000 * 1000] iteracji. Niestety nie miałem pomysłu, jak można to w miarę szubko zakodować, dlatego w momencie, kiedy mój kod zaczął wykonywać najgorszy przypadek w czasie około 0,7s stwierdziłem, że zostawię to tak, jak jest.Uważam, że dosyć istotnym zyskiem jest “skompresowanie” procesu alokowania pamięci do jednego odwołania do calloc() - na początku miałem trzy alokacje dla każdego fragmentu tablicy wynikowej, co jednak zabierało cenne milisekundy.
Ciąg dalszy... stoi pod znakiem zapytania.
Ze względu na to, że konkurs odbywa się w wyjątkowo niesprzyjającym dla mnie okresie czasu [maj to już przedsesyjne zaliczenia, a czerwiec przynosi "upragnioną" sesję] nie wiem, czy uda mi się rozwiązać jeszcze jakieś zadanie. Prawie zdążyłem dzisiaj oddać Wspinaczkę, jednakże o godzinie 00:00 byłem "daleko w lesie", także runda druga niestety zakończy się dla mnie wynikiem równym status quo. Pecha nawet nie ruszyłem.Jutro popołudniu postaram się znaleźć chwilę wolnego, żeby spróbować z trzecią rundą, aczkolwiek jest już ona na dosyć wysokim poziomie [nie oszukujmy się, Wieże nie były wcale takie trudne ;]], także nie wiem, czy dam radę. Niektórzy z moich znajomych odpuścili sobie już na drugiej rundzie, ale może coś uda się naskrobać. ;]
Podsumowanie.
Tradycyjnie będę wdzięczny za wytknięcie wszelkiego rodzaju błędów w kodzie oraz komentarze dotyczące potencjalnych optymalizacji / dobrych praktyk, ktore można było w tym przypadku zastosować.Jeśli udało Wam się rozwiązać któreś z zadań z pierwszej albo drugiej rundy - możecie śmiało zamieścić kod w komentarzu używając tagu {code lang=“cpp”}{/code} w nawiasach kwadratowych - tak, tak - trzeba zamienić napisane przeze mnie nawiasy klamrowe na kwadratowe, wtedy kod zostanie ładnie pokolorowany. W razie czego spokojnie - poprawię sam.