Wybór 10 zadań egzaminacyjnych 1. (10p) Podać asymptotykę (.) i rozwiązanie dokładne dla równania rekurencyjnego: T(n) = T(n/2) + n; T(1) = 1 (n = 2k, k = 0, 1, 2, ... ) 2. (15p) Obliczanie n-tej liczby ciągu Fibonacciego wymaga, przy zastosowaniu oczywistej procedury iteracyjnej, O(n) operacji dodawania. Zakładając jednostkowy koszt operacji arytmetycznych dodawania i mnożenia (niezależnie od wielkości liczb występujących w operacjach) obliczyć złożoność pesymistyczną, dokładną i asymptotyczną, poniższej funkcji. Operacje przypisania i związane z manipulacjami parametrem n pominąć w koszcie. unsigned f(int n) // n>=0 { unsigned i=1, j=1, k=0, r=0, t; while(n>0) { if(n&1) { // 7 operacji arytmetycznych w tej sekcji t = r*j; r = i*j + r*k + t; i = i*k +t; } // 6 operacji arytmetycznych w tej sekcji t = j*j; j = 2*k*j + t; k = k*k + t; n >>=1; } return r; } 3. (10p) Podać przebieg obliczeń wg algorytmu Little'a optymalnego cyklu Hamiltona dla grafu skierowanego z następującymi kosztami gałęziowymi ('-' oznacza brak połączenia): 1 2 3 4 5 1 - 4 9 2 5 2 8 - 6 11 6 3 4 - - 1 10 4 5 12 7 - 12 5 11 4 5 7 - Przyjąć, że w przypadku niejednoznaczności wyboru gałęzi decyzyjnej pierwszeństwo ma gałąź leksykograficznie wcześniejsza. 4. (15p) Na zbiorze P = { p0 , p1 , ... pn-1 } punktów płaszczyzny rozpięto n krawędzi. Każda krawędź ei jest reprezentowana przez parę indeksów (i1, i2) określającą dwa punkty końcowe pi1, pi2 tej krawędzi należące do P. Podać procedurę decyzyjną, która na podstawie dostarczonej tablicy krawędzi stwierdza, czy krawędzie te tworzą wielokąt na zbiorze punktów P. Prototyp odpowiedniej funkcji: 1 bool isPolygon(const Edge E[], int n, int S[]); Jeśli funkcja zwraca true, to tablica S zawiera sekwencję numerów punktów z P w kolejności obejścia wielokąta, S[0]==0; w przeciwnym przypadku zawartość tablicy S jest nieokreślona. 5. (15p) Suma elementów tablicy liczb całkowitych X[n] jest dodatnia. Napisać funkcję: void Arrange(int X[], int n); przestawiającą cyklicznie tablicę X tak, aby po przestawieniu wszystkie sumy Sk = (0 i <k) X[i], k=1, ..., n były dodatnie. Ocenić złożoność asymptotyczną zaproponowanego algorytmu. W algorytmie można wykorzystać co najwyżej O(1) pamięci pomocniczej. 6. (20) Macierz globalna A[n][n] reprezentuje graf nieskierowany G z n węzłami o numerach 0..n-1. Jest to macierz symetryczna w której A[i][j]==1 oznacza krawędź {i, j}; brak krawędzi reprezentowany jest zerem. Napisać funkcję: int Components(int C[], int n); zwracającą liczbę komponentów grafu G i wypełniającą tablicę C tak, że C[k] jest numerem komponentu do którego należy węzeł k. Numeracja komponentów rozpoczyna się od 1. Komponentem grafu nieskierowanego nazywamy maksymalny podgraf spójny. Jaka jest złożoność zaproponowanego algorytmu?. 7. (15p). Deskryptor prostokąta jest czwórką (x1, x2, y1, y2), gdzie x1<x2 oraz y1<y2, i reprezentuje zbiór punktów [x1, x2) [y1, y2), to znaczy obszar prostokątny prawostronnie otwarty. Podać możliwie efektywną funkcję decyzyjną, która dla zadanego zbioru n prostokątów S = { P0 , ... , Pn-1 } sprawdza, czy tworzy on pokrycie pewnego obszaru prostokątnego. Dokładniej, funkcja zwraca wartość prawdy, jeżeli istnieje prostokąt Q taki, że Q = Pi oraz Pi Pj = dla i j. W konwencjach języka C++ deklaracja funkcji może mieć postać: bool IsRectangle(int n, Rect *P[]); Podać ocenę złożoności asymptotycznej zaproponowanego algorytmu. 8. (8p). Wyznaczanie wartości minimalnej (albo maksymalnej) w zbiorze n liczb wymaga n-1 porównań. Oczywisty sposób wyznaczania minimum i maksimum ma koszt 2n - 3 porównań. Zaproponować usprawnienie pozwalające zmniejszyć koszt (liczbę porównań) wyznaczania minimum i maksimum przynajmniej o 20% dla dostatecznie dużych n. 9. (12p). Podać algorytm decyzyjny (i ocenić jego złożoność asymptotyczną w najgorszym przypadku) sprawdzania, czy zadany graf skierowany G = (V, E) jest acykliczny. Graf reprezentowany jest przy pomocy list incydencji: dla każdego węzła i V podana jest lista węzłów ik dołączonych do i gałęziami skierowanymi (i, ik). 10. (15p) (Uogólniony problem łączenia) Podać możliwie efektywny algorytm łączenia m uporządkowanych list liczb w jedną uporządkowaną listę wynikową. Wszystkie listy wejściowe zawierają łącznie n elementów. Wyznaczyć złożoność asymptotyczną zaproponowanego algorytmu jako funkcję parametrów m i n. Prototyp odpowiedniej funkcji może mieć postać: int Merge(int *L[],int m, int W[]); // Konwencja: L[i][0]== dlugość listy #i (0<=i<m) // Funkcja zwraca liczbe elementów (n) w tablicy wynikowej W[] 2