12
maj

Potyczki Algorytmiczne 2011: Zadanie „Wieże”.

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.

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.

Wejście:

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żę.

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ę.

Wyjście:

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:

#include <cstdlib>
#include <cstdio>

int main(void)
	{
	int size = 0, i, j;
	scanf("%d\n", &size);
	bool *rows = (bool *)calloc(size * (size + 2), sizeof(bool));
	char current = 0;
	// read
	for(i = 0; i < size; i++)
		{
		for(j = 0; j < size; j++)
			{
			scanf("%c", &current);
			if('\n' == current)
				{
				j--;
				continue;
				}
			if('W' == current)
				{
				rows[i] = true;
				rows[size + j] = true;
				rows[size * (i + 2) + j] = true;
				}
			}
		}
	// solve
	for(i = 0; i < size; i++)
		{
		for(j = 0; j < size; j++)
			{
			if(rows[size * (i + 2) + j] == true)
				{
				printf("W");
				}
			else if(rows[i] == false && rows[size + j] == false)
				{
				rows[i] = true;
				rows[size + j] = true;
				// rows[size * (i + 2) + j] = true;
				printf("W");
				}
			else
				{
				printf(".");
				}
			}
		printf("\n");
		}
	return 0;
	}

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 kwadratowychtak, tak – trzeba zamienić napisane przeze mnie nawiasy klamrowe na kwadratowe, wtedy kod zostanie ładnie pokolorowany. W razie czego spokojnie – poprawię sam.

Warto przeczytać.

Trwa ładowanie…

Subscribe without commenting

Wyszukaj:
Twitter
http://t.co/piYQJA2z /cc @merowing_ you'll like it :)
3 days ago
"It is about being polite, respectful and kind. That's the open source currency. Can't pay in these values? You shouldn't be using it."
4 days ago
Facebook
© Copyright 2010-2012 Tomasz Kowalczyk. All rights reserved. Created by Dream-Theme — premium wordpress themes. Proudly powered by WordPress.