Διδάσκων: Παύλος Παυλικκάς1 Ολυμπιάδα Πληροφορικής Recursion - Αναδρομή
Διδάσκων: Παύλος Παυλικκάς2 Αναδρομικές συναρτήσεις Αναδρομή (recursion) η τεχνική επίλυσης προβλημάτων σύμφωνα με την οποία τα μεγάλα προβλήματα λύνονται με αναγωγή τους σε μικρότερα προβλήματα της ίδιας μορφής. Αναδρομική συνάρτηση (recursive function) συνάρτηση η οποία καλεί τον εαυτό της
Διδάσκων: Παύλος Παυλικκάς3 Τυπική Αναδρομική Συνάρτηση if (έλεγχος απλής περίπτωσης) (απλή λύση που υπολογίζεται χωρίς τη χρήση αναδρομής) else (αναδρομική λύση με κλήση της ίδιας συνάρτησης)
Διδάσκων: Παύλος Παυλικκάς4 Παράδειγμα λύσης παραγοντικού με τη χρήση αναδρομής Αναδρομικός ορισμός παραγοντικού 0!=1 n!=n*(n-1)!, n>0
Διδάσκων: Παύλος Παυλικκάς5 #include using namespace std; int factorial( int n ); int main() { int num; cin >> num; cout << factorial( num ); return 0; } int factorial( int n ) { if ( n == 1 ) return 1; else return n * factorial( n-1 ); }
Διδάσκων: Παύλος Παυλικκάς6
7 Δύναμη αριθμού #include using namespace std; int power( int x, int n ); int main() { int a, b; cin >> a >> b; cout << power( a, b ); return 0; } int power( int x, int n ) { if ( n == 0 ) return 1; else return x * power( x, n-1 ); } π.χ. 2 3 Power(2,3)=2*Power(2,2) Power(2,2)=2*Power(2,1) Power(2,1)=2*Power(2,0) Power(2,0)=1 Power(2,3)=8
Διδάσκων: Παύλος Παυλικκάς8 Αριθμοί Fibonacci Ακολουθία αριθμών οι πρώτοι δύο όροι είναι το 0 και το 1 κάθε επόμενος όρος είναι το άθροισμα των δύο προηγούμενων f(0) = 0 f(1) = 1 f(2) = f(0) + f(1) = = 1 f(3) = f(1) + f(2) = = 2
Να δημιουργήσετε το πρόγραμμα που τυπώνει το n όρο της σειράς fibonacci. Το n δίνεται από το πρόγραμμα. #include using namespace std; int fibo( int n ); int main() { int a; cin >> a; cout << fibo( a ); return 0; } int fibo( int n ) { if ( n <= 1 ) return n; else return ( fibo( n-1 ) + fibo( n-2 ) ); } Διδάσκων: Παύλος Παυλικκάς9
Διδάσκων: Άκης Συκοπετρίτης10 Βρείτε το αποτέλεσμα του παρακάτω προγράμματος για Num=3 #include using namespace std; int f( int n ); int main() { int a; cin >> a; cout << f( a ); return 0; } int f( int n ) { if ( ( n == 1 ) || ( n == 0 ) ) return 1; else if ( n%2 == 0) return f( n/2 ) + 2; else return f( n-1 ) + 3; } Num=3 F(3)=F(2)+3 F(2)=F(1)+2 F(1)=1 F(3)=6
Μέγιστος κοινός διαιρέτης Μια ιδέα για να βρούμε τον μέγιστο κοινό διαιρέτη δύο αριθμών α, β είναι να δοκιμάσουμε όλους τους αριθμούς από το 1 μέχρι τον μικρότερο από τους α, β και να δούμε ποιος είναι ο μεγαλύτερος που διαιρεί και τους 2. Διδάσκων: Παύλος Παυλικκάς11
Μέγιστος κοινός διαιρέτης #include using namespace std; FILE *fin, *fout; void mkd( int x, int y, int result ); int main() { int a, b, c=0, z; fin = fopen( "mkd.in", "r" ); fout = fopen( "mkd.out", "w" ); fscanf( fin, "%d%d", &a, &b ); if( a>b ) c = b; else c = a; mkd( a, b, c ); fclose( fin ); fclose( fout ); return 0; } void mkd(int x, int y, int result) { if( (x % result == 0) && (y % result == 0) ) fprintf( fout, "%d\n", result ); else mkd( x, y, result-1 ); } Διδάσκων: Παύλος Παυλικκάς12
Διδάσκων: Παύλος Παυλικκάς13 Πύργοι του Hanoi Περιγραφή Να μεταφερθούν οι n δακτύλιοι από τον πρώτο στον τρίτο στύλο, χρησιμοποιώντας το δεύτερο ως βοηθητικό χώρο Κανόνες Ένας δακτύλιος τη φορά Δεν μπορεί να τοποθετηθεί μεγαλύτερος δακτύλιος πάνω από μικρότερο
Διδάσκων: Παύλος Παυλικκάς14 Για να λύσουμεαυτότοπρόβλημα σκεπτόμαστε ως εξής: Αρχικά, μεταφέρουμε τους ν ‐ 1 δίσκους στην μεσαία στήλη (Έστω B). (Δεν μας νοιάζει το πώς θα γίνει αυτό, κρατάμε μόνο την ιδέα για αρχή).
Στη συνέχεια μεταφέρουμε τον ν ‐ οστό δίσκο από την πρώτη στήλη (A) στην τρίτη (C). Διδάσκων: Παύλος Παυλικκάς15
Τέλος, μεταφέρουμε τους ν ‐ 1 δίσκους από την μεσαία στήλη (B), στην τελευταία (C). (Και πάλι δεν μας νοιάζει το πώς θα γίνει αυτό, κρατάμε μόνο την ιδέα). Διδάσκων: Παύλος Παυλικκάς16
Έστω τώρα μια διαδικασία (με όνομα moveDiscs), η οποία μεταφέρει x δίσκους από μία στήλη σε μία άλλη. Η διαδικασία αυτή θα έχει ως παραμέτρους τον αριθμό των δίσκων που θα μεταφερθούν, την στήλη αφετηρίας, την στήλη προορισμού, και την στήλη που δεν θα χρησιμοποιηθεί. moveDiscs(αριθμός_δίσκων, στήλη_αφετηρίας, στήλη_προορισμού, στήλη_που_δεν_χρησιμοποιώ) Διδάσκων: Παύλος Παυλικκάς17
Όταν ο αριθμός των δίσκων που θέλουμε να μεταφέρουμε γίνει ίσος με 1, δηλαδή μεταφέρουμε ένα μόνο δίσκο, τότε αυξάνουμε τον αριθμό κινήσεων που έχουμε κάνει και η moveDiscs σταματά. Σε κάθε άλλη περίπτωση ακολουθούμε την λογική που περιγράφτηκε πιο πάνω. Διδάσκων: Παύλος Παυλικκάς18
Αρχικά, μεταφέρουμε τους ν ‐ 1 δίσκους στην μεσαία στήλη (Έστω B). Δηλαδή εκτελούμε την moveDiscs(n ‐ 1, A, B, C); Διδάσκων: Παύλος Παυλικκάς19
Στη συνέχεια μεταφέρουμε τον ν ‐ οστό δίσκο από την πρώτη στήλη (A) στην τρίτη (C). Δηλαδή εκτελούμε την moveDiscs(1, A, C, B); Διδάσκων: Παύλος Παυλικκάς20
Τέλος, μεταφέρουμε τους ν ‐ 1 δίσκους από την μεσαία στήλη (B), στην τελευταία (C). Δηλαδή εκτελούμε την moveDiscs(n ‐ 1, B, C, A); Διδάσκων: Παύλος Παυλικκάς21
Διδάσκων: Παύλος Παυλικκάς22 #include using namespace std; void hanoi( int n, int bar1, int bar2, int bar3 ); int main() { hanoi(3, 1, 3, 2); return 0; } void hanoi( int n, int bar1, int bar2, int bar3 ) { if ( n==1 ) cout " << bar2 << "\n"; else { hanoi( n-1, bar1, bar3, bar2 ); hanoi( 1, bar1, bar2, bar3 ); hanoi( n-1, bar3, bar2, bar1 ); }
Το πρόβλημα των Ν-βασιλισσών Έχουμε μια σκακιέρα με Ν γραμμές και Ν στήλες. Σκοπός μας είναι να τοποθετήσουμε Ν βασίλισσες στην σκακιέρα έτσι ώστε καμία να μην απειλείται από καμία άλλη. Προφανώς σε κάθε γραμμή και σε κάθε στήλη θα υπάρχει μόνο μια βασίλισσα. Διδάσκων: Παύλος Παυλικκάς23
Αρχικά, ξεκινάμε από την πρώτη στήλη της σκακιέρας και δοκιμάζουμε να τοποθετήσουμε την βασίλισσα στην πρώτη γραμμή. Μετά, πηγαίνουμε στην δεύτερη στήλη και δοκιμάζουμε να τοποθετήσουμε την βασίλισσα στην πρώτη πάλι γραμμή. Προφανώς αυτό δεν γίνεται οπότε προσπαθούμε να τοποθετήσουμε την βασίλισσα στην δεύτερη γραμμή. Ούτε και αυτό γίνεται οπότε τοποθετούμε την βασίλισσα στην τρίτη γραμμή Διδάσκων: Παύλος Παυλικκάς24
Συνεχίζουμε την διαδικασία για τις επόμενες βασίλισσες στις επόμενες στήλες. Αν διαπιστώσουμε ότι δεν μπορούμε να τοποθετήσουμε πουθενά μια βασίλισσα, τότε αφαιρούμε την αμέσως προηγούμενη βασίλισσα που τοποθετήσαμε και την τοποθετούμε σε μια άλλη θέση. Μετά συνεχίζουμε κανονικά την διαδικασία. Όταν φτάσουμε στην Ν+1 ‐ οστή στήλη (πράγμα που σημαίνει ότι έχουμε ήδη τοποθετήσει την Ν ‐ οστή βασίλισσα) σταματάμε. Το πρόβλημα έχει λυθεί. Διδάσκων: Παύλος Παυλικκάς25
Η λύση να γίνει από τους μαθητές Διδάσκων: Παύλος Παυλικκάς26