380 likes | 572 Views
Algorytmy i Struktury Danych Typy algorytmów. Wykład 3 Prowadzący: dr Paweł Drozda. Plan wykładu. Brute force Rekurencje Metoda zachłanna Programowanie dynamiczne. Brute force. Sukcesywne sprawdzanie wszystkich kombinacji, aż do rozwiązania problemu
E N D
Algorytmy i Struktury DanychTypy algorytmów Wykład 3 Prowadzący: dr Paweł Drozda
Plan wykładu Bruteforce Rekurencje Metoda zachłanna Programowanie dynamiczne dr Paweł Drozda
Bruteforce • Sukcesywne sprawdzanie wszystkich kombinacji, aż do rozwiązania problemu • Zazwyczaj nieoptymalna, prosta do implementacji • Ogromna złożoność obliczeniowa • Przykłady: • Łamanie hasła • Znajdowanie pary punktów najmniej odległych • Wyszukiwanie wzorca w tekście dr Paweł Drozda
Wyszukiwanie wzorca w tekście – bruteforce • Problem Poszukiwanie wzorca długości M znaków w tekście o długości N znaków • Rozwiązanie Indeksy i, j oznaczają miejsce poruszania się po wzorcu i po tekście Jeśli znajdziemy początek taki sam porównujemy kolejne znaki, aż do znalezienia znaku niezgodnego – przesunięcie początku przeszukania w tekście o 1, bądź do momentu przejścia całego wzorca – zwrócony zostanie indeks początku wzorca w tekście Po przejściu całego tekstu bez znalezienia wzorca – zwracany komunikat o niepowodzeniu przeszukania dr Paweł Drozda
Wyszukiwanie wzorca - implementacja Szukaj (string wzorzec, string tekst){ int i=0, j=0; while (i<strlen(wzorzec) && j<strlen(tekst)){ if wzorzec[i] != tekst[j] { j-=i-1; i=0; } else{ j++; i++; } } if (i==strlen(w)) cout << j-i; else cout << -1; } dr Paweł Drozda
Rekurencje • Przykład wprowadzający Dziecko rozrzuciło klocki – musi je pozbierać do pudełka zadanie polega na włożeniu po jednym klocku do pudełka do momentu aż wszystkie klocki znajdą się w pudełku • Cechy algorytmu rekurencyjnego • zakończenie algorytmu jasno określone • większy problem rozbity na problemy elementarne dr Paweł Drozda
Rekurencje – ilustracja • Problem • Dla tablicy n liczb określić czy istnieje liczba x • Rozwiązanie • Weź pierwszy niezbadany element tablicy n-elementowej • Jeśli jest to x wypisz sukces i zakończ • W przeciwnym przypadku zbadaj pozostałą część tablicy • Gdy po przejściu całej tablicy nie został znaleziony x wypisz porażka dr Paweł Drozda
Rekurencje – przykładowa implementacja #include <iostream.h> #include <stdlib.h> const n=10; inttab[n]={1,2,3,2,-7,44,5,1,0,-3}; void szukaj(inttab[n],intleft,intright,int x) // left, right = lewa i prawa granica obszaru poszukiwań // tab = tablica // x = wartość do odnalezienia { if (left>right) cout << "Element " << x << " nie został odnaleziony\n"; else if (tab[left]==x) cout << "Znalazłem szukany element "<< x << endl; else szukaj(tab,left+1,right,x); } • intmain() • { • szukaj(tab,0,n-1,7); • szukaj(tab,0,n-1,5); • } • // wyniki programu: • // Element 7 nie został odnaleziony • // Znalazłem szukany element dr Paweł Drozda
Analiza algorytmu • Zakończenie programu • Element odnaleziony • Przekroczenie zakresu tablicy • Duży problem rozbity na problemy elementarne • Z tablicy o wymiarze n schodzimy do tablicy o wymiarze n-1 • Instrukcja porównania dr Paweł Drozda
Rekurencje - schemat wykonywania • Przykład silnia unsigned long intsilnia(int x) { if (x==0) return 1; else return x*silnia(x-1); } 3*2! X=0? nie X=0? 2*1! nie 1*0! X=0? nie X=0? 1 tak dr Paweł Drozda
Rekurencje – pułapki (1) • Wykonywanie tych samych obliczeń wiele razy • Problem ciągu Fibonacciego f(0)= 1, f(1)=1 f(n) = f(n-1) + f(n-2) f(4) f(3) f(2) f(2) f(1) f(1) f(0) f(1) f(0) dr Paweł Drozda
Rekurencje – pułapki (2) • Wywoływanie rekurencji w nieskończoność intStadDoWiecznosci(int n) { if (n==1) return 1; else if ((n %2) == 0) // n parzyste return StadDoWiecznosci(n-2)*n;else return StadDoWiecznosci(n-1)*n; } Dla parzystych n – odwołania w nieskończoność dr Paweł Drozda
Rozwiązywanie rekurencji • Merge Sort • Rozwiązanie • Założenie • n jest całkowite • T(n) jest stałe dla małych n
czyli: założenie: Metoda podstawiania
Metoda podstawiania • warunek brzegowy:
Metoda podstawiania • Zamiana zmiennych
Metoda iteracyjna i-ty składnik ciągu: iterowanie kończymy gdy:
Metoda iteracyjna szereg geometryczny
Metoda rekurencji uniwersalnej koszt dzielenia/łączenia a podproblemów rowiązywanych w czasie n/b
Metoda rekurencji uniwersalnej dla dostatecznie dużych n: więc:
Metoda zachłanna • Główne zastosowanie – problemy optymalizacji • Wybór w danej chwili najkorzystniejszy • „Nadzieja” otrzymania globalnie optymalnego rozwiązania • Przykłady zastosowania: • Znajdowanie minimum (maksimum) w tablicy N liczb • Ciągły problem plecakowy • Kody Huffmana – kompresja danych wykorzystując tablicę częstości występowania znaków dr Paweł Drozda
Znajdowanie minimum - implementacja int min(inttab[]){ inti,minimum=tab[0]; for (i=1; i<length(tab);i++) if (tab[i]<minimum) minimum=tab[i]; return minimum; } dr Paweł Drozda
Problem plecakowy • Sformułowanie problemu Złodziej rabujący sklep znalazł n przedmiotów. Każdy z przedmiotów ma pewną wartość i pewną wagę. Problem polega na zmieszczeniu jak najwartościowszego łupu do plecaka mogącego pomieścić pewną liczbę kilogramów • Problem dyskretny Każdy przedmiot jest kradziony w całości – część przedmiotu jest bezwartościowa np. księgarnia, sklep monopolowy, skarbiec ze sztabami złota • Problem ciągły przedmiot można podzielić – część przedmiotu też ma wartość np. sklep mięsny, odzież na wagę, skarbiec ze złotym piaskiem dr Paweł Drozda
Problem plecakowy – przykład (1) Dyskretny • waga 15kg wartość • 120 zł waga 5kg wartość 60 zł • waga 15kg wartość • 120 zł waga 10kg wartość 100 zł waga 10kg wartość 100 zł waga 10kg wartość 100 zł waga 5kg wartość 60 zł Metoda zachłanna Rozwiązanie optymalne wartość kg: p1 = 12zł p2=10 zł p3=8 zł dr Paweł Drozda
Problem plecakowy – przykład (2) Ciągły • waga 10kg wartość • 80 zł waga 5kg wartość 60 zł • waga 15kg wartość • 120 zł waga 10kg wartość 100 zł waga 10kg wartość 100 zł waga 5kg wartość 60 zł wartość kg: p1 = 12zł p2=10 zł p3=8 zł Metoda zachłanna = rozwiązanie optymalne dr Paweł Drozda
Programowanie dynamiczne Główne zastosowanie – problem optymalizacji Podobne do metody „dziel i zwyciężaj” Stosowane gdy podproblemy nie są niezależne Każdy podproblem rozwiązywany tylko raz – wynik rozwiązania zapamiętywany dr Paweł Drozda
Etapy programowania dynamicznego Scharakteryzowanie struktury optymalnego rozwiązania Rekurencyjne zdefiniowanie kosztu optymalnego rozwiązania Obliczenie optymalnego kosztu metodą wstępującą Znalezienie optymalnego rozwiązania dr Paweł Drozda
Przykład – linie montażowe a1,1 a1,2 a1,3 a1,n e1 t1,1 t1,2 x1 e2 t2,1 t2,2 x2 a2,1 a2,2 a2,3 a2,n Dwie linie montażowe – każda z linii ma n stanowisk Na i-tym stanowisku linii 1 jest wykonywana ta sama czynność co na i-tym stanowisku linii 2 Czasy wykonania czynności są różne Czasy e i x są to odpowiednio czas umieszczenia elementu i zdjęcia elementu z linii Czasy t oznaczają czas potrzebny na przeniesienie elementu z jednej linii na drugą dr Paweł Drozda
Linie montażowe • Sformułowanie problemu Wskazanie stanowisk montażowych na obu liniach tak, aby czas montażu był jak najkrótszy • Algorytm bruteforce Dla każdej możliwej ścieżki obliczany jest czas montażu, a następnie wybór najkrótszego czasu Nie do przyjęcia – złożoność obliczeniowa jest nie mniejsza od 2n co dla dużych n jest nie do policzenia w zadawalającym czasie dr Paweł Drozda
Linie montażowe – przykład 7 9 3 4 8 4 2 2 3 1 3 4 3 4 2 1 2 2 1 2 8 5 6 4 5 7 Rozwiązanie optymalne: linia 1: stanowiska 1,3,6 linia 2: stanowiska 2,4,5 JAK DO TEGO DOJŚĆ??? dr Paweł Drozda
Rozwiązanie – programowanie dynamiczne(1) • Etap 1 – struktura optymalnego rozwiązania Najszybszy sposób montażu do stanowiska i-tego pierwszej linii: dla i=1 – istnieje tylko jeden sposób dla i>1 – dwa sposoby: • przejście ze stanowiska i-1 pierwszej linii – koszt przejścia pomijany • Przejście ze stanowiska i-1 drugiej linii – koszt równy t2,n-1 Dla stanowisk i-1 koszt przejścia jest optymalny – Własność optymalnej podstruktury Analogicznie dla stanowiska i-tego drugiej linii • Rozwiązanie problemu dla stanowiska i na każdej z linii znalezienie rozwiązania podproblemów stanowisk i-1 dla każdej z linii dr Paweł Drozda
Rozwiązanie – programowanie dynamiczne(2) • Etap 2 – rozwiązanie rekurencyjne f= min(f1[n]+ x1 , f2[n] + x2) – najkrótszy czas montażu Wartości dla stanowisk 1: f1[1]=e1 + a1,1 f2[1]=e2 + a2,1 Sformułowanie równania dla dowolnego i: f1[i]=min(f1[i-1]+ a1,i, f2[i-1]+ t2,i-1 + a1,i) f2[i]=min(f2[i-1]+ a2,i, f1[i-1]+ t1,i-1 + a2,i) dr Paweł Drozda
Rozwiązanie – programowanie dynamiczne(3) • Obliczenia • funkcja f oznacza optymalne rozwiązanie • tabele s1, s2 dla i-tego stanowiska zawierają numer linii z której pochodzi i-1 stanowisko w optymalnym rozwiązaniu f1[1]=e1 + a1,1 f2[1]=e2 + a2,1 for i=1 to n if (f1[i-1]+ a1,i < f2[i-1]+ t2,i-1 + a1,i) f1[i]=f1[i-1]+ a1,i, s1[i]=1 else f1[i]=f2[i-1]+ t2,i-1 + a1,i, s2[i]=2 analogicznie dla drugiej linii if (f1[n]+ x1 < f2[n] + x2) f= f1[n]+ x1, s=1 else f= f2[n] + x2, s=2 dr Paweł Drozda
Rozwiązanie – programowanie dynamiczne(4) • Etap 4 – optymalne rozwiązanie Odczytanie odpowiednich numerów linii ze zmiennej s oraz z tablic s1, s2 w kolejności od n-tego do pierwszego stanowiska montażu dr Paweł Drozda
Problem montażu – rozwiązanie liczbowe f1[1]=9 f1[2]=min(9+9, 12+2+9)=18, s1[2]=1 f1[3]=20, s1[3]=2 f2[1]=12 f2[2]=min(12+5, 9+2+5)=16, s2[2]=1 f2[3]=22, s2[3]=2 f1[4]=24, s1[4]=1 f1[5]=32, s1[5]=1 f1[6]=35, s1[6]=2 f2[4]=25, s2[4]=1 f2[5]=30, s2[5]=2 f2[6]=37, s2[6]=2 f=38, s=1 numery linii dla poszczególnych wierzchołków od końca: 6-1, 5-2, 4-2, 3-1, 2-2, 1-1 7 9 3 4 8 4 2 2 3 1 3 4 3 4 2 1 2 2 1 2 8 5 6 4 5 7 dr Paweł Drozda