• Nie Znaleziono Wyników

Powered by TCPDF (www.tcpdf.org)

N/A
N/A
Protected

Academic year: 2021

Share "Powered by TCPDF (www.tcpdf.org)"

Copied!
3
0
0

Pełen tekst

(1)

1 MATEMATYKA DYSKRETNA - wykÃlad 5

dr in˙z Krzysztof Bry´s

Algorytmy generuj¸ace podstawowe obiekty kombinatoryczne

Cz¸esto, w szczeg´olno´sci przy projektowaniu algorytm´ow peÃlnego przegl¸adu, potrzebna jest umiej¸etno´s´c wygenerowania wszystkich obiekt´ow kombinatorycznych danego rodzaju. Przed- stawimy teraz kilka algorytm´ow, kt´ore wypisuj¸a wszystkie permutacje, kombinacje i podziaÃly zbioru. Nale˙zy zaznaczy´c, ˙ze metod generowania wszystkich takich obiekt´ow jest wiele i ka˙zdy z czytelnik´ow jest z pewno´sci¸a w stanie zapropojektowa´c wÃlasn¸a metod¸e. Zaproponowane tu- taj metody s¸a efektywne a r´ownocze´snie charakteryzuj¸a si¸e prostot¸a budowy. Ich poprawno´s´c wydaje si¸e by´c oczywista.

Algorytm generuj¸acy list¸e wszystkich permutacji zbioru [n]

Przedstawiony poni˙zej algorytm jest algorytmem indukcyjnym, to znaczy w k-tym kroku zakÃladamy, ˙ze krok k − 1-szy algorytmu wygenerowaÃl poprawn¸a list¸e wszystkich pemrutacji zbioru [k − 1]. Zaczynamy oczywi´scie od wygenerowania listy wszystkich permutacji zbioru [1], kt´ora skÃlada si¸e z jedynej permutacji tego zbioru.

Krok 1.

L1 := (1)

Dla ka˙zdego k = 2, . . . , n wykonaj krok k:

Krok k. ZaÃl´o˙zmy, ˙ze mamy wygenerowan¸a list¸e wszystkich permutacji zbioru [k − 1]:

Lk−1= (p1, p2, . . . , p(k−1)!)

Niech pi,j b¸edzie permutacj¸a zbioru [k] powstaÃl¸a z permutacji pi zbioru [k − 1] przez dodanie k na j-tej pozycji. Wtedy

Lk := (p1,1, p1,2, . . . , p1,k, p2,1, p2,2, . . . , p2,k, . . . , p(k−1)!,1, p(k−1)!,2, . . . , p(k−1)!,k)

Poprawno´s´c algorytmu: Fakt, ˙ze dla ka˙zdego k = 2, . . . , n ka˙zda permutacja zbioru [k]

pojawia si¸e na li´scie Lk dokÃladnie raz wynika z dw´och dosy´c oczywistych fakt´ow:

1) Po dodaniu liczby k na pewnej pozycji w dowolnej permutacji zbioru [k−1] otrzymujmey permutacj¸e zbioru [k] (bo [k] = [k − 1] ∪ {k})

2) Po usuni¸eciu liczby k z dowolnej permutacji zbioru [k] otrzymujemy permutacj¸e zbioru [k − 1] (jest to wÃla´snie ta permutacja zbioru [k − 1], z kt´orej powstaÃla).

Zatem kazda permutacja zbioru [k] powstaje z dokÃladnie jednej permutacji zbioru [k − 1]

przez dodanie liczby k na pewnej pozycji.

PrzykÃlad Stworzymy list¸e L3 wszystkich permutacji zbioru [4]. Zach¸ecamy, w ramach pracy samodzielnej, do rozszerzenia jej do listy L4 lub nawet L5.

Najpierw tworzymy list¸e L1:

L1 = ((1))

333

(2)

2 Potem tworzymy L2 dodaj¸ac w jedynej permutacji z listy L1 liczb¸e 2 wpierw na pierwszej a potem na drugiej pozycji:

L2 = ((2, 1), (1, 2))

Nast¸epnie generujemy L3 bior¸ac wpierw pierwsz¸a permutacj¸e (2, 1) z listy L2 i dodaj¸ac liczb¸e 3 kolejno na pocz¸atku, w ´srodku i na ko´ncu a potem to samo robimy z drug¸a permutacj¸a (1, 2) z listy L2:

L3 = ((3, 2, 1), (2, 3, 1), (2, 1, 3), (3, 1, 2), (1, 3, 2), (1, 2, 3))

Algorytm generuj¸acy wszystkie k-elementowe podzbiory (kombinacje) zbioru [n]

Podamy tym razem algorytm rekurencyjny (to znaczy taki kt´ory odwoÃluje si¸e sam do siebie ale dla mniejszych warto´sci argument´ow). Algorytm ten mo˙ze zosta´c napisany jako algorytm programowania dynamicznego, to znaczy obliczenia mog¸a zosta´c wykonane w p¸etli pocz¸awszy od najmniejszych warto´s´ci parametr´ow a ko´ncz¸ac na docelowych.

Niech

G(n, k) b¸edzie list¸a wszystkich k-elementowych podzbior´ow (kombinacji) zbioru [n] oraz G(n − 1, k − 1) ∪ {n} b¸edzie list¸a powstaÃl¸a z G(n − 1, k − 1) przez dodanie liczby n do ka˙zdego zbioru na li´scie G(n − 1, k − 1).

Wtedy algorytm generuje list¸e G(n, k) nast¸epuj¸acy spos´ob:

G(i, 1) = ({1}, {2}, . . . , {i}) dla ka˙zdego i = 1, . . . , n

czyli dla k = 1 otrzymujemy list¸e 1-elementowych podzbior´ow zbioru [i], ka˙zdy element tego zbioru tworzy oddzielny 1-elementowy podzbi´or na tej li´scie.

G(i, i) = ([i]) dla ka˙zdego i = 1, . . . , n

czyli dla n = k otrzymujemy list¸e na kt´orej znajduje si¸e caÃly zbi´or (bo jest jedynym i- elementowym podzbiorem zbioru [i])

G(n, k) = (G(n − 1, k), G(n − 1, k − 1) ∪ {n}) je´sli 1 < k < n

czyli w tym ostatnim przypadku lista G(n, k) powstaje z poÃl¸aczenia (konkatenacji) list G(n − 1, k) i G(n − 1, k − 1) ∪ {n}.

Poprawno´s´c algorytmu Fakt, ˙ze ka˙zdy podzbi´or k-elementowy zbioru [n] wyst¸epuje dokÃladnie raz na li´scie G(n, k) wynika z tego, ˙ze ka˙zdy podzbi´or k-elementowy zbioru [n]

zawiera liczb¸e n i jest wtedy na li´scie G(n − 1, k − 1) ∪ {n} (bo powstaje z pewnego k − 1- elementowego podzbioru zbioru [n−1] praze dodanie liczby n) albo jej nie zawiera i jest wtedy na li´scie G(n − 1, k) (bo jest r´ownie˙z k-elementowym podzbiorem zbioru [n − 1])

PrzykÃlad Wygenerujmy list¸e G(4, 2) wszystkich 2-elementowych podzbior´ow (kombinacji) zbioru [4]. Jak wiemy, takich podzbior´ow (par nieuporz¸adkowanych) jest C42 =³42´= 6.

Poniewa˙z 2 < 4, to

G(4, 2) = G(3, 2), G(3, 1) ∪ {4}.

(3)

3 Teraz tworzymy potrzebne listy. Wpierw G(3, 2):

G(3, 2) = G(2, 2), G(2, 1) ∪ {3}

przy czym G(2, 2) i G(2, 1) s¸a listami ”trywialnymi”. Mianowicie:

G(2, 2) = ({1, 2}) oraz

G(2, 1) = ({1}, {2}) a st¸ad

G(2, 1) ∪ {3} = ({1, 3}, {2, 3}).

Wracaj¸ac do pocz¸atku:

G(3, 2) = ({1, 2}, {1, 3}, {2, 3})

Nast¸epnie tworzymy list¸e G(3, 1) ∪ {4}. Lista G(3, 1) skÃlada si¸e z wszystkich 1-elementowych podzbior´ow zbioru [3] czyli

G(3, 1) = ({1}, {2}, {3}) a zatem:

G(3, 1) ∪ {4} = ({1, 4}, {2, 4}, {3, 4}).

Ostatecznie otrzymujemy:

G(4, 2) = ({1, 2}, {1, 3}, {2, 3}, {1, 4}, {2, 4}, {3, 4})

Taka lista jest przykÃladowo list¸a wszystkich spotka´n jakie musz¸a ze sob¸a rozegra´c cztery zespoÃly piÃlkarskie (np. w jednej grupie na mistrzostwach ´swiata) graj¸ace systemem ka˙zdy z ka˙zdym (wersja dla kobiet: prosz¸e wyobrazi´c sobie, ˙ze chodzi o kobiece zespoÃly piÃlkarskie).

Zauwa˙zmy ze wszystkie k-elementowe wariacje zbioru [n] mo˙zna otrzyma´c przez wygen- erowanie wpierw wszystkich k-elementowych kombinacji zbioru [n] a potem wygenerowanie dla ka˙zdej z otrzymanych kombinacji wszystkich permutacji. Tak wi¸ec nie zachodzi potrzeba projektowania oddzielnego algorytmu generuj¸acego wszystkie k-elementowe wariacje zbioru [n].

Algorytm generuj¸acy wszystkie podziaÃly zbioru [n]

Padamy teraz algorytm kunstruuj¸acy list¸e Lnwszystkich podziaÃl´ow zbioru [n]. Pocz¸atkowa lista L1 skÃlada si¸e oczywi´scie z jedynego podziaÃlu zbioru [1]. W ka˙zdym kolejnym kroku, dla k = 2, . . . , n, jest konstruowana lista Lk wszystkich podziaÃl´ow zbioru [k] na podstawie listy Lk−1 wszytskich podziaÃl´ow zbioru [k − 1].

Krok 1.

L1 := (1)

Dla ka˙zdego k = 2, . . . , n wykonaj krok k:

Krok k. ZaÃl´o˙zmy, ˙ze mamy wygenerowan¸a list¸e Lk−1 wszystkich podziaÃl´ow zbioru [k − 1].

List¸e Lk tworzymy w nast¸epuj¸acy spos´ob:

Powered by TCPDF (www.tcpdf.org) Powered by TCPDF (www.tcpdf.org)

Cytaty

Powiązane dokumenty