Przeskocz do treści

Delta mi!

Informatyczny kącik olimpijski

Czworokąty wypukłe

Tomasz Idziaszek

o artykule ...

  • Publikacja w Delcie: kwiecień 2013
  • Publikacja elektroniczna: 30-03-2013

W tym kąciku zajmiemy się zadaniem Quadrilaterals z obozu w Petrozawodsku w 2006 roku. Na płaszczyźnie dane jest math punktów w położeniu ogólnym (tzn. żadna trójka punktów nie leży na jednej prostej). Należy wyznaczyć liczbę czworokątów wypukłych, których wierzchołki znajdują się wśród podanych punktów.

Aby sprawdzić, czy punkty math mogą być kolejnymi wierzchołkami czworokąta wypukłego w porządku przeciwnym do kierunku ruchu wskazówek zegara, wystarczy zbadać, czy każda trójka kolejnych punktów tworzy zakręt w lewo. W tym celu można zbadać znak iloczynu wektorowego:

display-math

Sprawdzając wszystkie możliwe czwórki uporządkowane, liczbę „dobrych czwórek” możemy wyznaczyć w czasie math  Liczbę czworokątów wypukłych uzyskamy, dzieląc liczbę „dobrych czwórek” przez 4 (bierzemy poprawkę na obroty cykliczne).

obrazek

Rys. 1 Dwa przypadki położenia nieuporządkowanej czwórki punktów: A (po lewej) i B (po prawej).

Rys. 1 Dwa przypadki położenia nieuporządkowanej czwórki punktów: A (po lewej) i B (po prawej).

Aby otrzymać szybsze rozwiązanie, skorzystamy z pewnego pomysłowego triku. Rozważmy dowolną nieuporządkowaną czwórkę punktów (w położeniu ogólnym) i zastanówmy się, jakie czworokąty można na niej zbudować. W zależności od wzajemnego ustawienia punktów mamy dwa przypadki (patrz Rys. 1): albo wszystkie punkty leżą na brzegu otoczki wypukłej (przypadek A), albo trzy punkty leżą na brzegu otoczki wypukłej, a czwarty punkt w środku (przypadek B). Łatwo przekonać się, że w pierwszym przypadku czwórka punktów wyznacza jeden czworokąt wypukły, natomiast w drugim przypadku dostajemy trzy różne czworokąty wklęsłe.

Powiemy, że para punktów math tworzy przecięcie z parą punktów math jeśli punkty math leżą po różnych stronach prostej wyznaczonej przez punkty math Zauważmy, że czwórka punktów z przypadku A generuje nam dwa przecięcia (gdy za punkty math weźmiemy przeciwległe wierzchołki czworokąta wypukłego), natomiast w przypadku B są to trzy przecięcia (gdy jeden z punktów math leży w środku otoczki wypukłej). Niech math będzie liczbą wszystkich przecięć w zadanym zbiorze math punktów, natomiast math i  math będą liczbą czwórek punktów tworzących układy odpowiednio typu A i typu B. Możemy napisać następujący układ równań:

display-math

Rozwiązując ten układ, dostajemy, że liczba czworokątów wypukłych to math (przy okazji: liczba wszystkich czworokątów to math).

Pozostaje pokazać, jak wyznaczyć liczbę math Jeśli dla ustalonej pary punktów math dokładnie math punktów leży po jednej stronie prostej math i  math punktów leży po drugiej stronie tej prostej, to mamy math przecięć zawierających parę math Rozważając każdą taką parę math osobno, uzyskujemy czas math

obrazek

Rys. 2 Przejście prostej ze stanu math do stanu math a następnie do math

Rys. 2 Przejście prostej ze stanu math do stanu math a następnie do math

Szybciej wyznaczymy math korzystając z metody zamiatania. Ustalmy punkt math i przesuńmy punkty na płaszczyźnie tak, żeby środek układu współrzędnych znalazł się w  math Dla każdego innego punktu math wyznaczmy kąt math jaki tworzy półprosta math z osią math  Niech math będzie listą tych punktów posortowaną rosnąco względem kątów math czyli względem kątów, jakie tworzy prosta math z osią math  Na początku przyjmujemy math i wyznaczamy liczby math i  math punktów, które leżą powyżej i poniżej prostej math (tj. odpowiednio na lewo i na prawo od wektora math). W każdym kolejnym kroku math zmieniamy punkt math na math i uaktualniamy math i  math (patrz Rys. 2):

ifα (q) <  π then y  = y+ 1 else x  = x + 1;
      i
ifα (qi +1) < π then x  = x− 1 else y  = y − 1;
Ponieważ dla ustalonego punktu math sortowanie zajmie czas math  a przejrzenie – czas math  więc cały algorytm wykona się w czasie math  Uzyskany wynik (sumę iloczynów math) musimy podzielić przez 2, gdyż interesują nas nieuporządkowane pary punktów math