Pro každou z bílých figurek chceme zjistit, zda je ohrožována aspoň jednou černou. Můžeme zkusit vyzkoušet pro každou dvojici bílé a černé figurky, zda se ohrožují. Těchto dvojic je ovšem až kvadraticky mnoho a navíc se nám může stát, že i když by se dvojice ohrožovala, tak se mezi nimi nachází další figurka, která černé figurce z naší dvojice překáží ve výhledu a znemožňuje jí bílou figurku sebrat. Protože ověřit, zda dvojici nepřekáží ve výhledu další figurka, trvá lineárně dlouho, toto řešení je O(n3).

Jelikož černé figurky jsou pouze věže a střelci, bílé figurky mohou být ohroženy pouze z dohromady osmi směrů, kterými se černé dokážou pohybovat. Řešení můžeme vylepšit tím, že budeme zjišťovat, zda je bílá figurka ohrožena, pro každý směr zvlášť. Například pokud chceme pro každou bílou figurku zjistit, zda je ohrožena zleva nebo zprava, stačí nám uvažovat pouze ty figurky, které leží na stejném řádku. Navíc každá figurka má na svém řádku nejvýše dva sousedy, jednoho zleva, druhého zprava. Stačí nám uvažovat jen tyto sousedy, protože budou všem ostatním figurkám na řádku překážet ve výhledu. Pro každou z lineárně mnoho bílých figurek tedy v lineárním čase najdeme ty figurky, které s nimi sdílí řádek (pro ostatní směry ty, které sdílí sloupec či diagonálu), v lineárním čase najdeme mezi nimi dva nejbližší sousedy bílé figurky a pro ty vyzkoušíme, zda figurku neohrožují, to jest zda se jedná o černé figurky a jestli jsou typu, který se umí v tomto směru pohybovat. Celkově je toto řešení O(n · (n + n)), tedy O(n2).

Abychom uměli rychle zjistit, které figurky leží na stejném řádku, můžeme si nejprve všechny figurky seřadit podle jejich souřadnice řádku. V seřazeném seznamu figurek leží figurky na stejném řádku vedle sebe. Pokud bychom navíc vzali všechny figurky na stejném řádku a seřadili je podle souřadnice sloupce a uložili do nějakého pole, budeme je mít uspořádané v tom pořadí, v jakém leží na řádku za sebou. Pro libovolnou figurku na řádku tedy umíme najít její sousedy prostě tak, že se podíváme v tomto uspořádaném poli na index o jedna nižší a o jedna vyšší.

Tato dvě setřídění můžeme provést zároveň. Primárně figurky setřídíme podle souřadnice řádku, sekundárně pak podle souřadnice sloupce. Takové uspořádání, kde třídíme primárně podle jednoho kritéria a sekundárně podle jiného, se nazývá lexikografické. Nyní nám stačí projít setříděné pole a pro každou bílou figurku se podívat na její dva sousedy a rozhodnout, zda ji neohrožují. Také musíme dát pozor na to, že sousední figurky v setříděném poli figurek se nemusí nacházet na stejném řádku. Pokud je soused bíle figurky na jiném řádku, znamená to, že v daném směru se už na stejném řádku nenachází žádné figurky. Také si všimněme, že tímto uspořádáním najdeme všechny takové figurky, které bíle ohrožují ne jen z jednoho směru z osmi, ale ze dvou (zprava i zleva).

Kompletní řešení pro každou ze čtyř „os“ (doleva-doprava, nahoru-dolů, diagonálně doprava nahoru, diagonálně doprava dolů) lexikograficky figurky uspořádá, uspořádané pole v lineárním čase projde a pro každou bílou figurku určí, zda je ohrožována. Toto řešení má tedy časovou složitost O(n log n).

Program (C)

Kuba Pelc