שאלת מבחן במבוא למדעי המחשב - האוניברסיטה הפתוחה 2019 - רקורסיה עם מעקב
חלק א – עליכם לענות על כל השאלות בחלק זה במחברת הבחינה
שאלה 1 (25 נקודות)
נתון מערך דו-ממדי mat המלא במספרים אפס או אחד. נגדיר מסלול חוקי במערך כמסלול שעובר מתא המקור (source) לתא היעד (destination) ועובר רק בתאים שערכם הוא 1. אפשר לעבור מתא אחד לשני רק אם הוא שכן שלו מימין, משמאל, למעלה או למטה. לא באלכסון. כמו כן, אסור שיהיו מעגלים במסלול, כלומר, אי אפשר לבקר בתא שכבר היינו בו.
כתבו שיטה סטטית רקורסיבית המקבלת כפרמטרים מערך mat מלא באפסים ואחדים, וכן שני מספרים שלמים x ו- y, ומחזירה את אורכו של המסלול הארוך ביותר האפשרי במערך מתא המקור (0,0) לתא היעד .
לדוגמא, במערך להלן, אם הפרמטרים הם , , אורכו של המסלול הארוך ביותר מתא המקור (0,0) לתא היעד (2,5) הוא 16, ומסומן במערך.
חתימת השיטה היא:
השיטה צריכה להיות רקורסיבית ללא שימוש בלולאות כלל. כך גם כל שיטות העזר שתכתבו (אם תכתבו) לא יכולות להכיל לולאות.
אפשר להשתמש בהעמסת-יתר (overloading).
מותר לשנות את המערך במהלך השיטה, אבל בסופה הוא צריך לחזור למצבו המקורי.
אין צורך לדאוג ליעילות השיטה, אבל כמובן שצריך לשים לב לא לעשות קריאות רקורסיביות מיותרות! אל תשכחו לתעד את מה שכתבתם!
שאלה 1 (25 נקודות)
נתון מערך דו-ממדי mat המלא במספרים אפס או אחד. נגדיר מסלול חוקי במערך כמסלול שעובר מתא המקור (source) לתא היעד (destination) ועובר רק בתאים שערכם הוא 1. אפשר לעבור מתא אחד לשני רק אם הוא שכן שלו מימין, משמאל, למעלה או למטה. לא באלכסון. כמו כן, אסור שיהיו מעגלים במסלול, כלומר, אי אפשר לבקר בתא שכבר היינו בו.
כתבו שיטה סטטית רקורסיבית המקבלת כפרמטרים מערך mat מלא באפסים ואחדים, וכן שני מספרים שלמים x ו- y, ומחזירה את אורכו של המסלול הארוך ביותר האפשרי במערך מתא המקור (0,0) לתא היעד .
לדוגמא, במערך להלן, אם הפרמטרים הם , , אורכו של המסלול הארוך ביותר מתא המקור (0,0) לתא היעד (2,5) הוא 16, ומסומן במערך.
חתימת השיטה היא:
השיטה צריכה להיות רקורסיבית ללא שימוש בלולאות כלל. כך גם כל שיטות העזר שתכתבו (אם תכתבו) לא יכולות להכיל לולאות.
אפשר להשתמש בהעמסת-יתר (overloading).
מותר לשנות את המערך במהלך השיטה, אבל בסופה הוא צריך לחזור למצבו המקורי.
אין צורך לדאוג ליעילות השיטה, אבל כמובן שצריך לשים לב לא לעשות קריאות רקורסיביות מיותרות! אל תשכחו לתעד את מה שכתבתם!
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד 832019סמסטר ב
★★★★★
רקורסיה עם מעקבמערך דו-ממדישיטות סטטיותOverloading
כדי למצוא את המסלול הארוך ביותר, יש לחקור את כל המסלולים האפשריים. חשבו על פונקציה רקורסיבית שבודקת את כל שכניה ואיך ניתן להשתמש בתוצאות המוחזרות מהם. כיצד ניתן למנוע מעגלים ולזכור אילו תאים כבר נכללו במסלול הנוכחי?
הבעיה דורשת למצוא את המסלול הארוך ביותר במבוך המיוצג על ידי מערך דו-ממדי, מתא המקור לתא יעד . זוהי בעיה קלאסית שניתן לפתור באמצעות רקורסיה עם נסיגה רקורסיבית (backtracking). הרעיון המרכזי הוא לחקור באופן רקורסיבי את כל המסלולים החוקיים האפשריים מהמקור ליעד, ולבחור את הארוך מביניהם.
כדי לממש זאת, נשתמש בשיטת עזר רקורסיבית. השיטה הציבורית
1. שיטת עזר רקורסיבית: נגדיר שיטת עזר פרטית (או מועמסת) שתקבל, בנוסף למערך וליעד, גם את הקואורדינטות של התא הנוכחי במסלול. חתימתה יכולה להיות:
2. מניעת מעגלים (מעקב): על פי הגדרת הבעיה, אסור לבקר באותו תא יותר מפעם אחת במסלול. כדי לאכוף זאת, בכל פעם שאנו מבקרים בתא , נסמן אותו כ"תא שכבר ביקרנו בו". מכיוון שמותר לשנות את המערך, דרך נוחה לעשות זאת היא לשנות את ערך התא
3. תנאי עצירה (Base Cases):
4. הצעד הרקורסיבי:
5. שיטת המעטפת הציבורית:
השיטה
כדי לממש זאת, נשתמש בשיטת עזר רקורסיבית. השיטה הציבורית
longestPath תשמש כמעטפת שתפעיל את הרקורסיה מההתחלה.אסטרטגיית הפתרון:
1. שיטת עזר רקורסיבית: נגדיר שיטת עזר פרטית (או מועמסת) שתקבל, בנוסף למערך וליעד, גם את הקואורדינטות של התא הנוכחי במסלול. חתימתה יכולה להיות:
longestPathHelper(mat, r, c, dest_r, dest_c).2. מניעת מעגלים (מעקב): על פי הגדרת הבעיה, אסור לבקר באותו תא יותר מפעם אחת במסלול. כדי לאכוף זאת, בכל פעם שאנו מבקרים בתא , נסמן אותו כ"תא שכבר ביקרנו בו". מכיוון שמותר לשנות את המערך, דרך נוחה לעשות זאת היא לשנות את ערך התא
mat[r][c] מ-1 ל-0 באופן זמני. כך, בקריאות הרקורסיביות הבאות באותו מסלול, התא הזה ייחשב כ"קיר" ולא נוכל לחזור אליו.3. תנאי עצירה (Base Cases):
- כישלון: קריאה רקורסיבית מסתיימת בכישלון אם התא הנוכחי נמצא מחוץ לגבולות המערך, או אם ערכו הוא 0 (כלומר, הוא "קיר" או תא שכבר ביקרנו בו במסלול הנוכחי). במקרים אלו, אין מסלול חוקי מכאן, והשיטה תחזיר ערך מיוחד (sentinel) המציין כישלון, למשל -1.
- הצלחה: הקריאה הרקורסיבית מגיעה לתנאי עצירה חיובי כאשר התא הנוכחי הוא תא היעד. במקרה זה, מצאנו מסלול חוקי. אורך המסלול מתא היעד לעצמו הוא 1 (התא עצמו). לכן, השיטה תחזיר 1.
4. הצעד הרקורסיבי:
- אם התא הנוכחי הוא תא חוקי (בגבולות המערך וערכו 1), נבצע את הצעדים הבאים:
- נסמן את התא הנוכחי כמבוקר:
mat[r][c] = 0. - נקרא רקורסיבית לשיטה עבור כל אחד מארבעת השכנים: למעלה, למטה, ימינה ושמאלה.
- נשמור את אורכי המסלולים המוחזרים מכל אחת מארבע הקריאות.
- נסיגה (Backtrack): לאחר שכל הקריאות הרקורסיביות חזרו, חובה לשחזר את ערך התא המקורי:
mat[r][c] = 1. שחזור זה מאפשר למסלולים פוטנציאליים אחרים, שאינם חלק מהמסלול הנוכחי, להשתמש בתא זה. - נחשב את
max_path_from_neighbors, שהוא האורך המקסימלי מבין ארבעת הערכים שהוחזרו מהשכנים. אם כל השכנים החזירו -1 (כלומר, מאף אחד מהם אין מסלול ליעד), אז גם מהתא הנוכחי אין מסלול, ונחזיר -1. - אחרת, אורך המסלול הארוך ביותר מהתא הנוכחי הוא 1 (עבור התא הנוכחי) ועוד האורך המקסימלי שנמצא מהשכנים:
1 + max_path_from_neighbors.
5. שיטת המעטפת הציבורית:
השיטה
public static int longestPath(int mat[][], int x, int y) תבדוק תחילה אם תא המקור חסום. אם כן, היא תחזיר 0. אחרת, היא תקרא לשיטת העזר הרקורסיבית עם נקודת ההתחלה . אם שיטת העזר מחזירה -1 (לא נמצא מסלול), שיטת המעטפת תחזיר 0. אחרת, היא תחזיר את האורך שהתקבל.מימוש ב-Java: