5. přednáška - Rozklad problému na podproblémy

Podobné dokumenty
Rozklad problému na podproblémy

Rozklad problému na podproblémy, rekurze

Rozklad problému na podproblémy, rekurze

Algoritmizace a programování

8. Rekurze. doc. Ing. Jiří Vokřínek, Ph.D. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze

3. přednáška. Obsah: Řídící struktury sekvence, if-else, switch, for, while, do-while. Zpracování posloupnosti

Dekompozice problému, rekurze

Algoritmizace a programování

4. Rekurze. BI-EP1 Efektivní programování Martin Kačer

Řídicí struktury. alg3 1

Datové struktury. Obsah přednášky: Definice pojmů. Abstraktní datové typy a jejich implementace. Algoritmizace (Y36ALG), Šumperk - 12.

Funkce a procedury. Jan Faigl. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze. Přednáška 5 A0B36PR1 Programování 1

9. přednáška - třídy, objekty

Část 1 Funkce, lokální proměnné a přidělování paměti. Funkce a procedury. Část 2 Cykly a řízení jejich průchodu. Část 3 Příklady

Rekurze. Pavel Töpfer, 2017 Programování 1-8 1

Rekurze. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 12.

Základy algoritmizace 4. Problémy, algoritmy, data

5 Rekurze a zásobník. Rekurzivní volání metody

Spojové struktury. x, y, a, b. X1 y1 X2 y2 X3 y3. Grafické objekty bod. kružnice. obdélník. lomenáčára

1. Téma 12 - Textové soubory a výjimky

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

3 KTE / ZPE Informační technologie

KTE / ZPE Informační technologie

Funkce, intuitivní chápání složitosti

5. Dynamické programování

Algoritmizace. Cíle předmětu

Prohledávání do šířky = algoritmus vlny

Tato tematika je zpracována v Záznamy přednášek: str

Algoritmizace. Algoritmizace (Y36ALG), Šumperk - 1. přednáška 1

Úvod do programování - Java. Cvičení č.4

Paměť počítače. alg2 1

Datové struktury. alg12 1

Logické operace. Datový typ bool. Relační operátory. Logické operátory. IAJCE Přednáška č. 3. může nabýt hodnot: o true o false

Středoškolská technika 2017 PROGRAM NA GENEROVÁNÍ PRVOČÍSEL

int t1, t2, t3, t4, t5, t6, t7, prumer; t1=sys.readint();... t7=sys.readint(); prume pru r = r = ( 1+t 1+t t3+ t3+ t4 t5+ t5+ +t7 +t7 )/ ;

Seminář z IVT Algoritmizace. Slovanské gymnázium Olomouc Tomáš Kühr

Řešení: PŘENESVĚŽ (N, A, B, C) = přenes N disků z A na B pomocí C

Programování: základní konstrukce, příklady, aplikace. IB111 Programování a algoritmizace

Obsah 10. přednášky: Jak bude probíhat zkouška?! Podrobné informace:

C# konzole Podíl dvou čísel, podmínka IF

VYŠŠÍ ODBORNÁ ŠKOLA a STŘEDNÍ PRŮMYSLOVÁ ŠKOLA Mariánská 1100, Varnsdorf PROGRAMOVÁNÍ FUNKCE, REKURZE, CYKLY

Algoritmizace a programování

Binární soubory (datové, typované)

Rekurze. IB111 Úvod do programování skrze Python

8. přednáška: Soubory a proudy

Spojové struktury. Spojová struktura (linked structure):

Rekurze. Jan Faigl. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze. Přednáška 6 A0B36PR1 Programování 1

V každém kroku se a + b zmenší o min(a, b), tedy vždy alespoň o 1. Jestliže jsme na začátku dostali 2

Algoritmizace a programování

Základní pojmy. Úvod do programování. Základní pojmy. Zápis algoritmu. Výraz. Základní pojmy

Algoritmizace a programování. Terminálový vstup a výstup

Algoritmizace a programování

Dynamické programování

Algoritmizace a programování

Tato tematika je zpracována v Záznamy přednášek: str

Rekurze. Jan Hnilica Počítačové modelování 12

Úvod do programovacích jazyků (Java)

Algoritmizace Dynamické programování. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010

Časová složitost algoritmů

Úvod do informatiky. Miroslav Kolařík

KTE / ZPE Informační technologie

Rekurze a zásobník. Jak se vypočítá rekurzivní program? volání metody. vyšší adresy. main(){... fa(); //push ret1... } ret1

Poslední nenulová číslice faktoriálu

Základy algoritmizace. Hašování

ÚVODNÍ ZNALOSTI. datové struktury. správnost programů. analýza algoritmů

Algoritmizace a programování. Ak. rok 2012/2013 vbp 1. ze 44

Tato tematika je zpracována v Záznamy přednášek: str , 44-61

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 12.

Řídící struktury, if, while, switch

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 21.

součet cvičení celkem. známka. Úloha č.: max. bodů: skut. bodů:

6. Příkazy a řídící struktury v Javě

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Databáze, sítě a techniky programování X33DSP

Rekurze. Jan Faigl. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze. Přednáška 6 A0B36PR1 Programování 1

Úvod do programování 10. hodina

Martin Flusser. November 1, 2016

DobSort. Úvod do programování. DobSort Implementace 1/3. DobSort Implementace 2/3. DobSort - Příklad. DobSort Implementace 3/3

Řídicí příkazy KAPITOLA 3. Vstup znaků z klávesnice

Obsah přednášky. Příkaz for neúplný. Příkaz for příklady. Cyklus for each (enhanced for loop) Příkaz for příklady

Struktura programu v době běhu

ADT Seznam. dynamická množina. prvky vkládáme a vyjímáme na libovolné pozici (místě) v jejich posloupnosti (sekvenci) zásobník a fronta vs.

Základní stavební prvky algoritmu

Stromy. Příklady. Rekurzivní datové struktury. Základní pojmy

Slepé prohledávání do šířky Algoritmus prohledávání do šířky Při tomto způsobu prohledávání máme jistotu, že vždy nalezneme koncový stav, musíme ale p

Implementace LL(1) překladů

Rekurzivní algoritmy

Regulární výrazy. Vzory

2.1 Podmínka typu case Cykly Cyklus s podmínkou na začátku Cyklus s podmínkou na konci... 5

2 Strukturované datové typy Pole Záznam Množina... 4

Mimo samotné správnosti výsledku vypočteného zapsaným algoritmem je ještě jedno

Podmínky na zápočet. Java, zimní semestr

Programování v Pythonu

Obecná informatika. Matematicko-fyzikální fakulta Univerzity Karlovy v Praze. Podzim 2012

Algoritmizace a programování

Řetězce a řídicí struktury

IB111 Úvod do programování skrze Python

Seznamy a iterátory. Kolekce obecně. Rozhraní kolekce. Procházení kolekcí

Abstraktní datové typy: zásobník

Transkript:

5. přednáška - Rozklad problému na podproblémy Obsah přednášky: Rozklad problému na podproblémy. Rekurze. Algoritmizace (Y36ALG), Šumperk - 5. přednáška 1

Rozklad problému na podproblémy Postupný návrh programu rozkladem problému na podproblémy zadaný problém rozložíme na podproblémy pro řešení podproblémů zavedeme abstraktní příkazy s pomocí abstraktních příkazů sestavíme hrubéřešení abstraktní příkazy realizujeme pomocí metod Rozklad problému na podproblémy ilustrujme na příkladu hry NIM Pravidla: hráč zadá počet zápalek ( např. od 15 do 35 ) pak se střídá se strojem v odebírání; odebrat lze 1, 2 nebo 3 zápalky, prohraje ten, kdo odebere poslední zápalku. Dílčí podproblémy: zadání počtu zápalek odebrání zápalek hráčem odebrání zápalek strojem Algoritmizace (Y36ALG), Šumperk - 5. přednáška 2

Hra NIM Hrubéřešení: int pocet; boolean stroj = false; zadani_poctu_zapalek do { if ( stroj ) odebrani_zapalek_strojem else odebrani_zapalek_hracem stroj =!stroj; while ( pocet>0 ); if ( stroj ) vyhral_stroj else vyhral_hrac Podproblémy zadani_poctu_zapalek, odebrani_zapalek_strojem a odebrani_zapalek_hracem budeme realizovat metodami. Proměnné pocet a stroj pro ně budou statickými (čili nelokálními) proměnnými. Algoritmizace (Y36ALG), Šumperk - 5. přednáška 3

Hra NIM public class Nim { static int pocet; // aktuální počet zápalek static boolean stroj; // =true znamená, že bere počítač public static void main(string[] args) { zadanipoctu(); stroj = false; // zacina hrac do { if (stroj) berestroj(); else berehrac(); stroj =!stroj; while (pocet>0); if (stroj) System.out.println( "vyhral stroj" ); else System.out.println( "vyhral jste, gratuluji" ); static void zadanipoctu() { static void berehrac() { static void berestroj() { Algoritmizace (Y36ALG), Šumperk - 5. přednáška 4

Hra NIM static void zadanipoctu() { Scanner sc = new Scanner(System.in); do { System.out.println( "zadejte pocet zapalek (15-35)"); pocet = sc.nextint(); while (pocet<15 pocet>30); Algoritmizace (Y36ALG), Šumperk - 5. přednáška 5

Hra NIM static void berehrac() { int x; boolean chyba; Scanner sc = new Scanner(System.in); do { chyba = false; System.out.println( "pocet zapalek " + pocet ); System.out.println( "kolik odeberete" ); x = sc.nextint(); if (x<1) { System.out.println( "prilis malo" ); chyba = true; else if (x>3 x>pocet) { System.out.println( "prilis mnoho" ); chyba = true; while (chyba); pocet -= x; Algoritmizace (Y36ALG), Šumperk - 5. přednáška 6

Hra NIM Pravidla pro odebírání zápalek strojem, která vedou k vítězství (je-li to možné): počet zápalek nevýhodných pro protihráče je 1, 5, 9, atd., obecně 4n+1, kde n >0, stroj musí z počtu p zápalek odebrat x zápalek tak, aby platilo p x = 4n + 1 z tohoto vztahu po úpravě a s ohledem na omezení pro x dostaneme x = (p 1) mod 4 vyjde-li x=0, znamená to, že okamžitý počet zápalek je pro stroj nevýhodný a bude-li protihráč postupovat správně, stroj prohraje. static void berestroj() { System.out.println( "pocet zapalek " + pocet); int x = (pocet-1) % 4; if (x==0) x = 1; System.out.println( "odebiram " + x); pocet -= x; Algoritmizace (Y36ALG), Šumperk - 5. přednáška 7

Rekurze Rekurzivní algoritmus volá v průběhu svého běhu sám sebe. Příklad: výpočet faktoriálu: n! n! = 1, pro n 1 n! = n (n-1)!, pro n>1 Algoritmizace (Y36ALG), Šumperk - 5. přednáška 8

Rekurze Faktoriál pomocí rekurze a iterace static int fakt(int n) { if (n<=1) return 1; return n*fakt(n-1); static int fakt(int n) { if (n<=1) return 1; else return n*fakt(n-1); static int fakt(int n) { return n<=1?1:n*fakt(n-1); // ternární operátor Algoritmizace (Y36ALG), Šumperk - 5. přednáška 9

Faktoriál pomocí rekurze a iterace Iterace static int fakt(int n) { static int fakt(int n) { if (n<=1) return static 1; int fakt(int if (n<=1) n) { return 1; return n*fakt(n-1); int f = 1; else return n*fakt(n-1); while (n>1){ f *= n; n--; static int fakt(int n) { return f; return n<=1?1:n*fakt(n-1); // ternární operátor Algoritmizace (Y36ALG), Šumperk - 5. přednáška 10

Iterační algoritmus NSD() - připomínka Bez použití rekurze, iteračně static int nsd(int x, int y) { int zbytek; while( y!= 0 ) { zbytek = x % y; x = y; y = zbytek; return x; Kolikrát se provede tělo cyklu while? Platí: Je-li x y (> 0), pak x mod y < x/2 Důkaz: (př.: 55 88, 88 55, 55 33, 33 22, 22 11, 11 11, 11 0) buď je y x/2 nebo je y > x/2 y y y x / 2 y x x mod y x / 2 y x mod y Nechť n je počáteční hodnota y. Každé dva průchody cyklem se y zmenší na polovinu, takže na hodnotu 0 dospěje nejpozději po 2.log 2 n průchodech. Algoritmizace (Y36ALG), Šumperk - 5. přednáška 11 x

Rekurzivní algoritmus NSD() I Platí: je-li x, y > 0, pak nsd(x, y): je-li x = y, pak nsd(x,y) = x je-li x > y, pak nsd(x,y) = nsd(x%y, y) je-li x < y, pak nsd(x,y) = nsd(x, y%x) static int nsd(int x, int y) { if (x==y) return x; else if (x>y) return nsd(x%y, y); else return nsd(x, y%x); static int nsd(int x, int y) { int zbytek; while( y!= 0 ) { zbytek = x % y; x = y; y = zbytek; return x; Rekurze Iterace Algoritmizace (Y36ALG), Šumperk - 5. přednáška 12

Rekurze a rozklad problému na podproblémy Příklad: Program, který přečte posloupnost čísel zakončenou nulou a vypíše ji obráceně Rozklad problému: zavedeme abstraktní příkaz obrať posloupnost příkaz rozložíme do tří kroků: přečti číslo ( a ulož si ho ) if (přečtenéčíslo není nula) obrať posloupnost ( zbytek!! ) vypiščíslo ( uložené ) Algoritmizace (Y36ALG), Šumperk - 5. přednáška 13

Příklad rekurze Obrať posloupnost obrať posloupnost přečti číslo if (přečtenéčíslo není nula) obrať posloupnost, tj. zbytek vypiščíslo cti x if() 2 4 6 8 0 2 cti x if() 4 cti x if() 6 cti x 8 0 0 8 6 4 2 if() cti x 2 vypiš x 4 vypiš x 6 vypiš x 8 vypiš x if() vypiš x 0 Algoritmizace (Y36ALG), Šumperk - 5. přednáška 14

Řešení: Příklad rekurze - obrat() public class Obrat { static Scanner sc = new Scanner(System.in); public static void main(string[] args) { System.out.println("zadejte zakončenou nulou"); obrat(); static void obrat() { int x = sc.nextint(); // načtení if (x!=0) obrat(); // otočení zbytku System.out.print(x + " "); // výpis uloženého Algoritmizace (Y36ALG), Šumperk - 5. přednáška 15

Příklad rekurze - Hanojské věže a b c Úkol: přemístit disky na druhou jehlu s použitím třetí pomocné jehly, přičemž musíme dodržovat tato pravidla: - v každém kroku můžeme přemístit pouze jeden disk, a to vždy z jehly na jehlu (disky nelze odkládat mimo jehly), - není možné položit větší disk na menší. Algoritmizace (Y36ALG), Šumperk - 5. přednáška 16

Příklad rekurze - Hanojské věže 1 2 3 Zavedeme abstraktní příkaz prenes_vez(n,1,2,3) který interpretujeme jako "přenes n disků z jehly 1 na jehlu 2 s použitím jehly 3". Pro n>0 lze příkaz rozložit na tři jednodušší příkazy 1. prenes_vez(n-1,1,3,2) 2. "přenes disk z jehly 1 na jehlu 2" 3. prenes_vez(n-1,3,2,1) Algoritmizace (Y36ALG), Šumperk - 5. přednáška 17

Příklad rekurze - Hanojské věže public static void main(string[] args) { Scanner sc = new Scanner(System.in); System.out.println("zadejte výšku věže"); int pocetdisku = sc.nextint(); prenesvez(pocetdisku, 1, 2, 3); 3 přenes disk z 1 na 2 přenes disk z 1 na 3 přenes disk z 2 na 3 přenes disk z 1 na 2 přenes disk z 3 na 1 přenes disk z 3 na 2 přenes disk z 1 na 2 static void prenesvez (int vyska, int odkud, int kam, int pomoci) { if (vyska>0) { prenesvez(vyska-1, odkud, pomoci, kam); System.out.println("přenes disk z "+odkud+" na "+kam); prenesvez(vyska-1, pomoci, kam, odkud); Algoritmizace (Y36ALG), Šumperk - 5. přednáška 18

Příklad rekurze - Hanojské věže prenesvez(3, 1, 2, 3); prenesvez(2, 1, 3, 2); (1, 2); prenesvez(2, 3, 2, 1); prenesvez(1, 1, 2, 3); (1, 3); prenesvez(1, 2, 3, 1); prenesvez(1, 3, 1, 2); (3, 2); prenesvez(1, 1, 2, 3); (1, 2); (2, 3); (3, 1); (1, 2); prenesvez(int vyska, int odkud, int kam, int pomoci) { if (vyska>0) { prenesvez(vyska-1, odkud, pomoci, kam); System.out.println("přenes disk z "+odkud+" na "+kam); prenesvez(vyska-1, pomoci, kam, odkud); 3 přenes disk z 1 na 2 přenes disk z 1 na 3 přenes disk z 2 na 3 přenes disk z 1 na 2 přenes disk z 3 na 1 přenes disk z 3 na 2 přenes disk z 1 na 2 Algoritmizace (Y36ALG), Šumperk - 5. přednáška 19

Obecně k rekurzivitě Rekurzivní funkce (procedury) jsou přímou realizací rekurzivních algoritmů Rekurzivní algoritmus předepisuje výpočet shora dolů v závislosti na velikosti (složitosti) vstupních dat: pro nejmenší (nejjednodušší) data je výpočet předepsán přímo pro obecná data je výpočet předepsán s využitím téhož algoritmu pro menší (jednodušší) data Výhodou rekurzivních funkcí (procedur) je jednoduchost a přehlednost Nevýhodou může být časová náročnost způsobená např. zbytečným opakováním výpočtu Řadu rekurzívních algoritmů lze nahradit iteračními, které počítají výsledek zdola nahoru, tj, od menších (jednodušších) dat k větším (složitějším) Pokud algoritmus výpočtu zdola nahoru nenajdeme (např. při řešení problému Hanojských věží), lze rekurzivitu odstranit pomocí tzv. zásobníku Algoritmizace (Y36ALG), Šumperk - 5. přednáška 20

Fibonacciho posloupnost - historie Pingala (Chhandah-shāstra, the Art of Prosody, 450 or 200 BC) Leonardo Pisano (Leonardo z Pisy), známým také jako Fibonacci (cca 1175 1250) - králíci Henry E. Dudeney (1857-1930) - krávy Jestliže každá kráva vyprodukuje své první tele (jalovici) ve věku dvou let a poté každý rok jednu další jalovici, kolik budete mít krav za 12 let, jestliže Vám žádná nezemře? rok počet krav (jalovic) 1 1 2 1 3 2 počet krav = počet_krav_vloni + počet_narozených 4 3 // odpovídá počtu krav předloni) 5 5 f n = f n-1 + f n-2 6 8... 12 144... 50 20 365 011 074 (20 miliard) Algoritmizace (Y36ALG), Šumperk - 5. přednáška 21

Fibonacciho posloupnost - iteračně fibnminus2 fibnminus1 fibn i Platí: f 0 = 1 f 1 = 1 f n = f n-1 + f n-2, pro n > 1 Iteračně: static int fib(int n) { int i, fibnminus2=1, fibnminus1=1, fibn=1; for (i=2; i<=n; i++) { fibnminus2 = fibnminus1; fibnminus1 = fibn; fibn = fibnminus1 + fibnminus2; return fibn; 1 1 1 1 1 2 + 3 2 3 + 5 4 3 5 + 8 + Složitost: 3 n 1 2 2 3 5 Algoritmizace (Y36ALG), Šumperk - 5. přednáška 22

Fibonacciho posloupnost rekurzivne Platí: f 0 = 1 f 1 = 1 f n = f n-1 + f n-2, pro n > 1 Rekurzivní funkce: static int fib(int i) { if (i<2) return 1; return fib(i-1)+fib(i-2); Rekurze je hezká - zápis odpovídá rekurentní definici. Je ale i efektivní? Algoritmizace (Y36ALG), Šumperk - 5. přednáška 23

Složitost výpočtu Fibonaccihočísla Iterační metoda: 3*n Rekurzivní metoda: static int fib(int i) { if (i<2) return 1; return fib(i-1)+fib(i-2); příklad pro fib(10): fib(10) fib(9) + fib(8) fib(8) + fib(7) fib(7) + fib(6) fib(7) + fib(6) fib(6) + fib(5) fib(6) + fib(5) fib(5) + fib(4) Jaká to je složitost? Algoritmizace (Y36ALG), Šumperk - 5. přednáška 24

Složitost výpočtu Fibonaccihočísla Iterační metoda: 3*n Rekurzivní metoda: static int fib(int i) { if (i<2) return 1; return fib(i-1)+fib(i-2); příklad pro fib(10): fib(10) fib(9) + fib(8) fib(8) + fib(7) fib(7) + fib(6) fib(7) + fib(6) fib(6) + fib(5) fib(6) + fib(5) fib(5) + fib(4) Složitost je exponenciální!!! Algoritmizace (Y36ALG), Šumperk - 5. přednáška 25

Další příklady rekurze - fraktály Algoritmizace (Y36ALG), Šumperk - 5. přednáška 26

Příklad rekurze, základní schema součin public static void main(string[] args) { int x, y;...; System.out.println(" " + soui(x, y) + sour(x, y)); static int sour(int s, int t) { int sour; if (s > 0) sour = sour(s - 1, t) + t; else sour = 0; return sour; static int soui(int s, int t){ int soui=0; for (int i = 0; i < s; i++) soui=soui+t; return soui; Algoritmizace (Y36ALG), Šumperk - 5. přednáška 27 pro zájemce

Rozklad na prvočinitele Rozklad přirozeného čísla n na součin prvočísel Řešení: dělit 2, pak 3, atd., a dalšími prvočísly, n-1 každé dělení beze zbytku dodá jednoho prvočinitele Příklad: 60/2=>30/2=>15/3=>5/5 60 má prvočinitele 2, 2, 3, 5 Algoritmizace (Y36ALG), Šumperk - 5. přednáška 28 pro zájemce

Rozklad na prvočinitele - iterací public class PrvociniteleIter { static int rozklad(int x, int d) { while (d < x && x % d!= 0) d++; System.out.print(d + " "); return d; public static void main(string[] args) { Scanner sc = new Scanner(System.in); System.out.println("zadejte přirozené číslo: "); int x = sc.nextint(); if (x < 1) { System.out.println("číslo není přirozené"); System.exit(0); int d = 2; while (d <= x) { d = rozklad(x, d); x = x/d; zadejte přirozenéčíslo: 144 2 2 2 2 3 3 Algoritmizace (Y36ALG), Šumperk - 5. přednáška 29 pro zájemce

Rozklad na prvočinitele - rekurzí public class Prvocinitele { static void rozklad(int x, int d) { if (d <= x) { while (d < x && x%d!= 0) d++; System.out.print(d + " "); rozklad(x/d, d); public static void main(string[] args) { Scanner sc = new Scanner(System.in); System.out.println("zadejte přirozené číslo: "); int x = sc.nextint(); if (x < 1) { System.out.println("číslo není přirozené"); System.exit(0); rozklad(x, 2); zadejte přirozenéčíslo: 144 2 2 2 2 3 3 Algoritmizace (Y36ALG), Šumperk - 5. přednáška 30 pro zájemce